1130803Smarcel/* Objective-C language support routines for GDB, the GNU debugger.
2130803Smarcel
3130803Smarcel   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   Contributed by Apple Computer, Inc.
6130803Smarcel   Written by Michael Snyder.
7130803Smarcel
8130803Smarcel   This file is part of GDB.
9130803Smarcel
10130803Smarcel   This program is free software; you can redistribute it and/or modify
11130803Smarcel   it under the terms of the GNU General Public License as published by
12130803Smarcel   the Free Software Foundation; either version 2 of the License, or
13130803Smarcel   (at your option) any later version.
14130803Smarcel
15130803Smarcel   This program is distributed in the hope that it will be useful,
16130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
17130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18130803Smarcel   GNU General Public License for more details.
19130803Smarcel
20130803Smarcel   You should have received a copy of the GNU General Public License
21130803Smarcel   along with this program; if not, write to the Free Software
22130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
23130803Smarcel   Boston, MA 02111-1307, USA.  */
24130803Smarcel
25130803Smarcel#include "defs.h"
26130803Smarcel#include "symtab.h"
27130803Smarcel#include "gdbtypes.h"
28130803Smarcel#include "expression.h"
29130803Smarcel#include "parser-defs.h"
30130803Smarcel#include "language.h"
31130803Smarcel#include "c-lang.h"
32130803Smarcel#include "objc-lang.h"
33130803Smarcel#include "complaints.h"
34130803Smarcel#include "value.h"
35130803Smarcel#include "symfile.h"
36130803Smarcel#include "objfiles.h"
37130803Smarcel#include "gdb_string.h"		/* for strchr */
38130803Smarcel#include "target.h"		/* for target_has_execution */
39130803Smarcel#include "gdbcore.h"
40130803Smarcel#include "gdbcmd.h"
41130803Smarcel#include "frame.h"
42130803Smarcel#include "gdb_regex.h"
43130803Smarcel#include "regcache.h"
44130803Smarcel#include "block.h"
45130803Smarcel#include "infcall.h"
46130803Smarcel#include "valprint.h"
47130803Smarcel#include "gdb_assert.h"
48130803Smarcel
49130803Smarcel#include <ctype.h>
50130803Smarcel
51130803Smarcelstruct objc_object {
52130803Smarcel  CORE_ADDR isa;
53130803Smarcel};
54130803Smarcel
55130803Smarcelstruct objc_class {
56130803Smarcel  CORE_ADDR isa;
57130803Smarcel  CORE_ADDR super_class;
58130803Smarcel  CORE_ADDR name;
59130803Smarcel  long version;
60130803Smarcel  long info;
61130803Smarcel  long instance_size;
62130803Smarcel  CORE_ADDR ivars;
63130803Smarcel  CORE_ADDR methods;
64130803Smarcel  CORE_ADDR cache;
65130803Smarcel  CORE_ADDR protocols;
66130803Smarcel};
67130803Smarcel
68130803Smarcelstruct objc_super {
69130803Smarcel  CORE_ADDR receiver;
70130803Smarcel  CORE_ADDR class;
71130803Smarcel};
72130803Smarcel
73130803Smarcelstruct objc_method {
74130803Smarcel  CORE_ADDR name;
75130803Smarcel  CORE_ADDR types;
76130803Smarcel  CORE_ADDR imp;
77130803Smarcel};
78130803Smarcel
79130803Smarcel/* Lookup a structure type named "struct NAME", visible in lexical
80130803Smarcel   block BLOCK.  If NOERR is nonzero, return zero if NAME is not
81130803Smarcel   suitably defined.  */
82130803Smarcel
83130803Smarcelstruct symbol *
84130803Smarcellookup_struct_typedef (char *name, struct block *block, int noerr)
85130803Smarcel{
86130803Smarcel  struct symbol *sym;
87130803Smarcel
88130803Smarcel  sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0,
89130803Smarcel		       (struct symtab **) NULL);
90130803Smarcel
91130803Smarcel  if (sym == NULL)
92130803Smarcel    {
93130803Smarcel      if (noerr)
94130803Smarcel	return 0;
95130803Smarcel      else
96130803Smarcel	error ("No struct type named %s.", name);
97130803Smarcel    }
98130803Smarcel  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
99130803Smarcel    {
100130803Smarcel      if (noerr)
101130803Smarcel	return 0;
102130803Smarcel      else
103130803Smarcel	error ("This context has class, union or enum %s, not a struct.",
104130803Smarcel	       name);
105130803Smarcel    }
106130803Smarcel  return sym;
107130803Smarcel}
108130803Smarcel
109130803SmarcelCORE_ADDR
110130803Smarcellookup_objc_class (char *classname)
111130803Smarcel{
112130803Smarcel  struct value * function, *classval;
113130803Smarcel
114130803Smarcel  if (! target_has_execution)
115130803Smarcel    {
116130803Smarcel      /* Can't call into inferior to lookup class.  */
117130803Smarcel      return 0;
118130803Smarcel    }
119130803Smarcel
120130803Smarcel  if (lookup_minimal_symbol("objc_lookUpClass", 0, 0))
121130803Smarcel    function = find_function_in_inferior("objc_lookUpClass");
122130803Smarcel  else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0))
123130803Smarcel    function = find_function_in_inferior("objc_lookup_class");
124130803Smarcel  else
125130803Smarcel    {
126130803Smarcel      complaint (&symfile_complaints, "no way to lookup Objective-C classes");
127130803Smarcel      return 0;
128130803Smarcel    }
129130803Smarcel
130130803Smarcel  classval = value_string (classname, strlen (classname) + 1);
131130803Smarcel  classval = value_coerce_array (classval);
132130803Smarcel  return (CORE_ADDR) value_as_long (call_function_by_hand (function,
133130803Smarcel							   1, &classval));
134130803Smarcel}
135130803Smarcel
136130803SmarcelCORE_ADDR
137130803Smarcellookup_child_selector (char *selname)
138130803Smarcel{
139130803Smarcel  struct value * function, *selstring;
140130803Smarcel
141130803Smarcel  if (! target_has_execution)
142130803Smarcel    {
143130803Smarcel      /* Can't call into inferior to lookup selector.  */
144130803Smarcel      return 0;
145130803Smarcel    }
146130803Smarcel
147130803Smarcel  if (lookup_minimal_symbol("sel_getUid", 0, 0))
148130803Smarcel    function = find_function_in_inferior("sel_getUid");
149130803Smarcel  else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0))
150130803Smarcel    function = find_function_in_inferior("sel_get_any_uid");
151130803Smarcel  else
152130803Smarcel    {
153130803Smarcel      complaint (&symfile_complaints, "no way to lookup Objective-C selectors");
154130803Smarcel      return 0;
155130803Smarcel    }
156130803Smarcel
157130803Smarcel  selstring = value_coerce_array (value_string (selname,
158130803Smarcel						strlen (selname) + 1));
159130803Smarcel  return value_as_long (call_function_by_hand (function, 1, &selstring));
160130803Smarcel}
161130803Smarcel
162130803Smarcelstruct value *
163130803Smarcelvalue_nsstring (char *ptr, int len)
164130803Smarcel{
165130803Smarcel  struct value *stringValue[3];
166130803Smarcel  struct value *function, *nsstringValue;
167130803Smarcel  struct symbol *sym;
168130803Smarcel  struct type *type;
169130803Smarcel
170130803Smarcel  if (!target_has_execution)
171130803Smarcel    return 0;		/* Can't call into inferior to create NSString.  */
172130803Smarcel
173130803Smarcel  sym = lookup_struct_typedef("NSString", 0, 1);
174130803Smarcel  if (sym == NULL)
175130803Smarcel    sym = lookup_struct_typedef("NXString", 0, 1);
176130803Smarcel  if (sym == NULL)
177130803Smarcel    type = lookup_pointer_type(builtin_type_void);
178130803Smarcel  else
179130803Smarcel    type = lookup_pointer_type(SYMBOL_TYPE (sym));
180130803Smarcel
181130803Smarcel  stringValue[2] = value_string(ptr, len);
182130803Smarcel  stringValue[2] = value_coerce_array(stringValue[2]);
183130803Smarcel  /* _NSNewStringFromCString replaces "istr" after Lantern2A.  */
184130803Smarcel  if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0))
185130803Smarcel    {
186130803Smarcel      function = find_function_in_inferior("_NSNewStringFromCString");
187130803Smarcel      nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
188130803Smarcel    }
189130803Smarcel  else if (lookup_minimal_symbol("istr", 0, 0))
190130803Smarcel    {
191130803Smarcel      function = find_function_in_inferior("istr");
192130803Smarcel      nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
193130803Smarcel    }
194130803Smarcel  else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0))
195130803Smarcel    {
196130803Smarcel      function = find_function_in_inferior("+[NSString stringWithCString:]");
197130803Smarcel      stringValue[0] = value_from_longest
198130803Smarcel	(builtin_type_long, lookup_objc_class ("NSString"));
199130803Smarcel      stringValue[1] = value_from_longest
200130803Smarcel	(builtin_type_long, lookup_child_selector ("stringWithCString:"));
201130803Smarcel      nsstringValue = call_function_by_hand(function, 3, &stringValue[0]);
202130803Smarcel    }
203130803Smarcel  else
204130803Smarcel    error ("NSString: internal error -- no way to create new NSString");
205130803Smarcel
206130803Smarcel  VALUE_TYPE(nsstringValue) = type;
207130803Smarcel  return nsstringValue;
208130803Smarcel}
209130803Smarcel
210130803Smarcel/* Objective-C name demangling.  */
211130803Smarcel
212130803Smarcelchar *
213130803Smarcelobjc_demangle (const char *mangled, int options)
214130803Smarcel{
215130803Smarcel  char *demangled, *cp;
216130803Smarcel
217130803Smarcel  if (mangled[0] == '_' &&
218130803Smarcel     (mangled[1] == 'i' || mangled[1] == 'c') &&
219130803Smarcel      mangled[2] == '_')
220130803Smarcel    {
221130803Smarcel      cp = demangled = xmalloc(strlen(mangled) + 2);
222130803Smarcel
223130803Smarcel      if (mangled[1] == 'i')
224130803Smarcel	*cp++ = '-';		/* for instance method */
225130803Smarcel      else
226130803Smarcel	*cp++ = '+';		/* for class    method */
227130803Smarcel
228130803Smarcel      *cp++ = '[';		/* opening left brace  */
229130803Smarcel      strcpy(cp, mangled+3);	/* tack on the rest of the mangled name */
230130803Smarcel
231130803Smarcel      while (*cp && *cp == '_')
232130803Smarcel	cp++;			/* skip any initial underbars in class name */
233130803Smarcel
234130803Smarcel      cp = strchr(cp, '_');
235130803Smarcel      if (!cp)	                /* find first non-initial underbar */
236130803Smarcel	{
237130803Smarcel	  xfree(demangled);	/* not mangled name */
238130803Smarcel	  return NULL;
239130803Smarcel	}
240130803Smarcel      if (cp[1] == '_') {	/* easy case: no category name     */
241130803Smarcel	*cp++ = ' ';		/* replace two '_' with one ' '    */
242130803Smarcel	strcpy(cp, mangled + (cp - demangled) + 2);
243130803Smarcel      }
244130803Smarcel      else {
245130803Smarcel	*cp++ = '(';		/* less easy case: category name */
246130803Smarcel	cp = strchr(cp, '_');
247130803Smarcel	if (!cp)
248130803Smarcel	  {
249130803Smarcel	    xfree(demangled);	/* not mangled name */
250130803Smarcel	    return NULL;
251130803Smarcel	  }
252130803Smarcel	*cp++ = ')';
253130803Smarcel	*cp++ = ' ';		/* overwriting 1st char of method name...  */
254130803Smarcel	strcpy(cp, mangled + (cp - demangled));	/* get it back */
255130803Smarcel      }
256130803Smarcel
257130803Smarcel      while (*cp && *cp == '_')
258130803Smarcel	cp++;			/* skip any initial underbars in method name */
259130803Smarcel
260130803Smarcel      for (; *cp; cp++)
261130803Smarcel	if (*cp == '_')
262130803Smarcel	  *cp = ':';		/* replace remaining '_' with ':' */
263130803Smarcel
264130803Smarcel      *cp++ = ']';		/* closing right brace */
265130803Smarcel      *cp++ = 0;		/* string terminator */
266130803Smarcel      return demangled;
267130803Smarcel    }
268130803Smarcel  else
269130803Smarcel    return NULL;	/* Not an objc mangled name.  */
270130803Smarcel}
271130803Smarcel
272130803Smarcel/* Print the character C on STREAM as part of the contents of a
273130803Smarcel   literal string whose delimiter is QUOTER.  Note that that format
274130803Smarcel   for printing characters and strings is language specific.  */
275130803Smarcel
276130803Smarcelstatic void
277130803Smarcelobjc_emit_char (int c, struct ui_file *stream, int quoter)
278130803Smarcel{
279130803Smarcel
280130803Smarcel  c &= 0xFF;			/* Avoid sign bit follies.  */
281130803Smarcel
282130803Smarcel  if (PRINT_LITERAL_FORM (c))
283130803Smarcel    {
284130803Smarcel      if (c == '\\' || c == quoter)
285130803Smarcel	{
286130803Smarcel	  fputs_filtered ("\\", stream);
287130803Smarcel	}
288130803Smarcel      fprintf_filtered (stream, "%c", c);
289130803Smarcel    }
290130803Smarcel  else
291130803Smarcel    {
292130803Smarcel      switch (c)
293130803Smarcel	{
294130803Smarcel	case '\n':
295130803Smarcel	  fputs_filtered ("\\n", stream);
296130803Smarcel	  break;
297130803Smarcel	case '\b':
298130803Smarcel	  fputs_filtered ("\\b", stream);
299130803Smarcel	  break;
300130803Smarcel	case '\t':
301130803Smarcel	  fputs_filtered ("\\t", stream);
302130803Smarcel	  break;
303130803Smarcel	case '\f':
304130803Smarcel	  fputs_filtered ("\\f", stream);
305130803Smarcel	  break;
306130803Smarcel	case '\r':
307130803Smarcel	  fputs_filtered ("\\r", stream);
308130803Smarcel	  break;
309130803Smarcel	case '\033':
310130803Smarcel	  fputs_filtered ("\\e", stream);
311130803Smarcel	  break;
312130803Smarcel	case '\007':
313130803Smarcel	  fputs_filtered ("\\a", stream);
314130803Smarcel	  break;
315130803Smarcel	default:
316130803Smarcel	  fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
317130803Smarcel	  break;
318130803Smarcel	}
319130803Smarcel    }
320130803Smarcel}
321130803Smarcel
322130803Smarcelstatic void
323130803Smarcelobjc_printchar (int c, struct ui_file *stream)
324130803Smarcel{
325130803Smarcel  fputs_filtered ("'", stream);
326130803Smarcel  objc_emit_char (c, stream, '\'');
327130803Smarcel  fputs_filtered ("'", stream);
328130803Smarcel}
329130803Smarcel
330130803Smarcel/* Print the character string STRING, printing at most LENGTH
331130803Smarcel   characters.  Printing stops early if the number hits print_max;
332130803Smarcel   repeat counts are printed as appropriate.  Print ellipses at the
333130803Smarcel   end if we had to stop before printing LENGTH characters, or if
334130803Smarcel   FORCE_ELLIPSES.  */
335130803Smarcel
336130803Smarcelstatic void
337130803Smarcelobjc_printstr (struct ui_file *stream, char *string,
338130803Smarcel	       unsigned int length, int width, int force_ellipses)
339130803Smarcel{
340130803Smarcel  unsigned int i;
341130803Smarcel  unsigned int things_printed = 0;
342130803Smarcel  int in_quotes = 0;
343130803Smarcel  int need_comma = 0;
344130803Smarcel
345130803Smarcel  /* If the string was not truncated due to `set print elements', and
346130803Smarcel     the last byte of it is a null, we don't print that, in
347130803Smarcel     traditional C style.  */
348130803Smarcel  if ((!force_ellipses) && length > 0 && string[length-1] == '\0')
349130803Smarcel    length--;
350130803Smarcel
351130803Smarcel  if (length == 0)
352130803Smarcel    {
353130803Smarcel      fputs_filtered ("\"\"", stream);
354130803Smarcel      return;
355130803Smarcel    }
356130803Smarcel
357130803Smarcel  for (i = 0; i < length && things_printed < print_max; ++i)
358130803Smarcel    {
359130803Smarcel      /* Position of the character we are examining to see whether it
360130803Smarcel	 is repeated.  */
361130803Smarcel      unsigned int rep1;
362130803Smarcel      /* Number of repetitions we have detected so far.  */
363130803Smarcel      unsigned int reps;
364130803Smarcel
365130803Smarcel      QUIT;
366130803Smarcel
367130803Smarcel      if (need_comma)
368130803Smarcel	{
369130803Smarcel	  fputs_filtered (", ", stream);
370130803Smarcel	  need_comma = 0;
371130803Smarcel	}
372130803Smarcel
373130803Smarcel      rep1 = i + 1;
374130803Smarcel      reps = 1;
375130803Smarcel      while (rep1 < length && string[rep1] == string[i])
376130803Smarcel	{
377130803Smarcel	  ++rep1;
378130803Smarcel	  ++reps;
379130803Smarcel	}
380130803Smarcel
381130803Smarcel      if (reps > repeat_count_threshold)
382130803Smarcel	{
383130803Smarcel	  if (in_quotes)
384130803Smarcel	    {
385130803Smarcel	      if (inspect_it)
386130803Smarcel		fputs_filtered ("\\\", ", stream);
387130803Smarcel	      else
388130803Smarcel		fputs_filtered ("\", ", stream);
389130803Smarcel	      in_quotes = 0;
390130803Smarcel	    }
391130803Smarcel	  objc_printchar (string[i], stream);
392130803Smarcel	  fprintf_filtered (stream, " <repeats %u times>", reps);
393130803Smarcel	  i = rep1 - 1;
394130803Smarcel	  things_printed += repeat_count_threshold;
395130803Smarcel	  need_comma = 1;
396130803Smarcel	}
397130803Smarcel      else
398130803Smarcel	{
399130803Smarcel	  if (!in_quotes)
400130803Smarcel	    {
401130803Smarcel	      if (inspect_it)
402130803Smarcel		fputs_filtered ("\\\"", stream);
403130803Smarcel	      else
404130803Smarcel		fputs_filtered ("\"", stream);
405130803Smarcel	      in_quotes = 1;
406130803Smarcel	    }
407130803Smarcel	  objc_emit_char (string[i], stream, '"');
408130803Smarcel	  ++things_printed;
409130803Smarcel	}
410130803Smarcel    }
411130803Smarcel
412130803Smarcel  /* Terminate the quotes if necessary.  */
413130803Smarcel  if (in_quotes)
414130803Smarcel    {
415130803Smarcel      if (inspect_it)
416130803Smarcel	fputs_filtered ("\\\"", stream);
417130803Smarcel      else
418130803Smarcel	fputs_filtered ("\"", stream);
419130803Smarcel    }
420130803Smarcel
421130803Smarcel  if (force_ellipses || i < length)
422130803Smarcel    fputs_filtered ("...", stream);
423130803Smarcel}
424130803Smarcel
425130803Smarcel/* Create a fundamental C type using default reasonable for the
426130803Smarcel   current target.
427130803Smarcel
428130803Smarcel   Some object/debugging file formats (DWARF version 1, COFF, etc) do
429130803Smarcel   not define fundamental types such as "int" or "double".  Others
430130803Smarcel   (stabs or DWARF version 2, etc) do define fundamental types.  For
431130803Smarcel   the formats which don't provide fundamental types, gdb can create
432130803Smarcel   such types using this function.
433130803Smarcel
434130803Smarcel   FIXME: Some compilers distinguish explicitly signed integral types
435130803Smarcel   (signed short, signed int, signed long) from "regular" integral
436130803Smarcel   types (short, int, long) in the debugging information.  There is
437130803Smarcel   some disagreement as to how useful this feature is.  In particular,
438130803Smarcel   gcc does not support this.  Also, only some debugging formats allow
439130803Smarcel   the distinction to be passed on to a debugger.  For now, we always
440130803Smarcel   just use "short", "int", or "long" as the type name, for both the
441130803Smarcel   implicit and explicitly signed types.  This also makes life easier
442130803Smarcel   for the gdb test suite since we don't have to account for the
443130803Smarcel   differences in output depending upon what the compiler and
444130803Smarcel   debugging format support.  We will probably have to re-examine the
445130803Smarcel   issue when gdb starts taking it's fundamental type information
446130803Smarcel   directly from the debugging information supplied by the compiler.
447130803Smarcel   fnf@cygnus.com */
448130803Smarcel
449130803Smarcelstatic struct type *
450130803Smarcelobjc_create_fundamental_type (struct objfile *objfile, int typeid)
451130803Smarcel{
452130803Smarcel  struct type *type = NULL;
453130803Smarcel
454130803Smarcel  switch (typeid)
455130803Smarcel    {
456130803Smarcel      default:
457130803Smarcel	/* FIXME: For now, if we are asked to produce a type not in
458130803Smarcel	   this language, create the equivalent of a C integer type
459130803Smarcel	   with the name "<?type?>".  When all the dust settles from
460130803Smarcel	   the type reconstruction work, this should probably become
461130803Smarcel	   an error.  */
462130803Smarcel	type = init_type (TYPE_CODE_INT,
463130803Smarcel			  TARGET_INT_BIT / TARGET_CHAR_BIT,
464130803Smarcel			  0, "<?type?>", objfile);
465130803Smarcel        warning ("internal error: no C/C++ fundamental type %d", typeid);
466130803Smarcel	break;
467130803Smarcel      case FT_VOID:
468130803Smarcel	type = init_type (TYPE_CODE_VOID,
469130803Smarcel			  TARGET_CHAR_BIT / TARGET_CHAR_BIT,
470130803Smarcel			  0, "void", objfile);
471130803Smarcel	break;
472130803Smarcel      case FT_CHAR:
473130803Smarcel	type = init_type (TYPE_CODE_INT,
474130803Smarcel			  TARGET_CHAR_BIT / TARGET_CHAR_BIT,
475130803Smarcel			  0, "char", objfile);
476130803Smarcel	break;
477130803Smarcel      case FT_SIGNED_CHAR:
478130803Smarcel	type = init_type (TYPE_CODE_INT,
479130803Smarcel			  TARGET_CHAR_BIT / TARGET_CHAR_BIT,
480130803Smarcel			  0, "signed char", objfile);
481130803Smarcel	break;
482130803Smarcel      case FT_UNSIGNED_CHAR:
483130803Smarcel	type = init_type (TYPE_CODE_INT,
484130803Smarcel			  TARGET_CHAR_BIT / TARGET_CHAR_BIT,
485130803Smarcel			  TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
486130803Smarcel	break;
487130803Smarcel      case FT_SHORT:
488130803Smarcel	type = init_type (TYPE_CODE_INT,
489130803Smarcel			  TARGET_SHORT_BIT / TARGET_CHAR_BIT,
490130803Smarcel			  0, "short", objfile);
491130803Smarcel	break;
492130803Smarcel      case FT_SIGNED_SHORT:
493130803Smarcel	type = init_type (TYPE_CODE_INT,
494130803Smarcel			  TARGET_SHORT_BIT / TARGET_CHAR_BIT,
495130803Smarcel			  0, "short", objfile);	/* FIXME-fnf */
496130803Smarcel	break;
497130803Smarcel      case FT_UNSIGNED_SHORT:
498130803Smarcel	type = init_type (TYPE_CODE_INT,
499130803Smarcel			  TARGET_SHORT_BIT / TARGET_CHAR_BIT,
500130803Smarcel			  TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
501130803Smarcel	break;
502130803Smarcel      case FT_INTEGER:
503130803Smarcel	type = init_type (TYPE_CODE_INT,
504130803Smarcel			  TARGET_INT_BIT / TARGET_CHAR_BIT,
505130803Smarcel			  0, "int", objfile);
506130803Smarcel	break;
507130803Smarcel      case FT_SIGNED_INTEGER:
508130803Smarcel	type = init_type (TYPE_CODE_INT,
509130803Smarcel			  TARGET_INT_BIT / TARGET_CHAR_BIT,
510130803Smarcel			  0, "int", objfile); /* FIXME -fnf */
511130803Smarcel	break;
512130803Smarcel      case FT_UNSIGNED_INTEGER:
513130803Smarcel	type = init_type (TYPE_CODE_INT,
514130803Smarcel			  TARGET_INT_BIT / TARGET_CHAR_BIT,
515130803Smarcel			  TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
516130803Smarcel	break;
517130803Smarcel      case FT_LONG:
518130803Smarcel	type = init_type (TYPE_CODE_INT,
519130803Smarcel			  TARGET_LONG_BIT / TARGET_CHAR_BIT,
520130803Smarcel			  0, "long", objfile);
521130803Smarcel	break;
522130803Smarcel      case FT_SIGNED_LONG:
523130803Smarcel	type = init_type (TYPE_CODE_INT,
524130803Smarcel			  TARGET_LONG_BIT / TARGET_CHAR_BIT,
525130803Smarcel			  0, "long", objfile); /* FIXME -fnf */
526130803Smarcel	break;
527130803Smarcel      case FT_UNSIGNED_LONG:
528130803Smarcel	type = init_type (TYPE_CODE_INT,
529130803Smarcel			  TARGET_LONG_BIT / TARGET_CHAR_BIT,
530130803Smarcel			  TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
531130803Smarcel	break;
532130803Smarcel      case FT_LONG_LONG:
533130803Smarcel	type = init_type (TYPE_CODE_INT,
534130803Smarcel			  TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
535130803Smarcel			  0, "long long", objfile);
536130803Smarcel	break;
537130803Smarcel      case FT_SIGNED_LONG_LONG:
538130803Smarcel	type = init_type (TYPE_CODE_INT,
539130803Smarcel			  TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
540130803Smarcel			  0, "signed long long", objfile);
541130803Smarcel	break;
542130803Smarcel      case FT_UNSIGNED_LONG_LONG:
543130803Smarcel	type = init_type (TYPE_CODE_INT,
544130803Smarcel			  TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
545130803Smarcel			  TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
546130803Smarcel	break;
547130803Smarcel      case FT_FLOAT:
548130803Smarcel	type = init_type (TYPE_CODE_FLT,
549130803Smarcel			  TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
550130803Smarcel			  0, "float", objfile);
551130803Smarcel	break;
552130803Smarcel      case FT_DBL_PREC_FLOAT:
553130803Smarcel	type = init_type (TYPE_CODE_FLT,
554130803Smarcel			  TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
555130803Smarcel			  0, "double", objfile);
556130803Smarcel	break;
557130803Smarcel      case FT_EXT_PREC_FLOAT:
558130803Smarcel	type = init_type (TYPE_CODE_FLT,
559130803Smarcel			  TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
560130803Smarcel			  0, "long double", objfile);
561130803Smarcel	break;
562130803Smarcel      }
563130803Smarcel  return (type);
564130803Smarcel}
565130803Smarcel
566130803Smarcel/* Determine if we are currently in the Objective-C dispatch function.
567130803Smarcel   If so, get the address of the method function that the dispatcher
568130803Smarcel   would call and use that as the function to step into instead. Also
569130803Smarcel   skip over the trampoline for the function (if any).  This is better
570130803Smarcel   for the user since they are only interested in stepping into the
571130803Smarcel   method function anyway.  */
572130803Smarcelstatic CORE_ADDR
573130803Smarcelobjc_skip_trampoline (CORE_ADDR stop_pc)
574130803Smarcel{
575130803Smarcel  CORE_ADDR real_stop_pc;
576130803Smarcel  CORE_ADDR method_stop_pc;
577130803Smarcel
578130803Smarcel  real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
579130803Smarcel
580130803Smarcel  if (real_stop_pc != 0)
581130803Smarcel    find_objc_msgcall (real_stop_pc, &method_stop_pc);
582130803Smarcel  else
583130803Smarcel    find_objc_msgcall (stop_pc, &method_stop_pc);
584130803Smarcel
585130803Smarcel  if (method_stop_pc)
586130803Smarcel    {
587130803Smarcel      real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc);
588130803Smarcel      if (real_stop_pc == 0)
589130803Smarcel	real_stop_pc = method_stop_pc;
590130803Smarcel    }
591130803Smarcel
592130803Smarcel  return real_stop_pc;
593130803Smarcel}
594130803Smarcel
595130803Smarcel
596130803Smarcel/* Table mapping opcodes into strings for printing operators
597130803Smarcel   and precedences of the operators.  */
598130803Smarcel
599130803Smarcelstatic const struct op_print objc_op_print_tab[] =
600130803Smarcel  {
601130803Smarcel    {",",  BINOP_COMMA, PREC_COMMA, 0},
602130803Smarcel    {"=",  BINOP_ASSIGN, PREC_ASSIGN, 1},
603130803Smarcel    {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
604130803Smarcel    {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
605130803Smarcel    {"|",  BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
606130803Smarcel    {"^",  BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
607130803Smarcel    {"&",  BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
608130803Smarcel    {"==", BINOP_EQUAL, PREC_EQUAL, 0},
609130803Smarcel    {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
610130803Smarcel    {"<=", BINOP_LEQ, PREC_ORDER, 0},
611130803Smarcel    {">=", BINOP_GEQ, PREC_ORDER, 0},
612130803Smarcel    {">",  BINOP_GTR, PREC_ORDER, 0},
613130803Smarcel    {"<",  BINOP_LESS, PREC_ORDER, 0},
614130803Smarcel    {">>", BINOP_RSH, PREC_SHIFT, 0},
615130803Smarcel    {"<<", BINOP_LSH, PREC_SHIFT, 0},
616130803Smarcel    {"+",  BINOP_ADD, PREC_ADD, 0},
617130803Smarcel    {"-",  BINOP_SUB, PREC_ADD, 0},
618130803Smarcel    {"*",  BINOP_MUL, PREC_MUL, 0},
619130803Smarcel    {"/",  BINOP_DIV, PREC_MUL, 0},
620130803Smarcel    {"%",  BINOP_REM, PREC_MUL, 0},
621130803Smarcel    {"@",  BINOP_REPEAT, PREC_REPEAT, 0},
622130803Smarcel    {"-",  UNOP_NEG, PREC_PREFIX, 0},
623130803Smarcel    {"!",  UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
624130803Smarcel    {"~",  UNOP_COMPLEMENT, PREC_PREFIX, 0},
625130803Smarcel    {"*",  UNOP_IND, PREC_PREFIX, 0},
626130803Smarcel    {"&",  UNOP_ADDR, PREC_PREFIX, 0},
627130803Smarcel    {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
628130803Smarcel    {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
629130803Smarcel    {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
630130803Smarcel    {NULL, OP_NULL, PREC_NULL, 0}
631130803Smarcel};
632130803Smarcel
633130803Smarcelstruct type ** const (objc_builtin_types[]) =
634130803Smarcel{
635130803Smarcel  &builtin_type_int,
636130803Smarcel  &builtin_type_long,
637130803Smarcel  &builtin_type_short,
638130803Smarcel  &builtin_type_char,
639130803Smarcel  &builtin_type_float,
640130803Smarcel  &builtin_type_double,
641130803Smarcel  &builtin_type_void,
642130803Smarcel  &builtin_type_long_long,
643130803Smarcel  &builtin_type_signed_char,
644130803Smarcel  &builtin_type_unsigned_char,
645130803Smarcel  &builtin_type_unsigned_short,
646130803Smarcel  &builtin_type_unsigned_int,
647130803Smarcel  &builtin_type_unsigned_long,
648130803Smarcel  &builtin_type_unsigned_long_long,
649130803Smarcel  &builtin_type_long_double,
650130803Smarcel  &builtin_type_complex,
651130803Smarcel  &builtin_type_double_complex,
652130803Smarcel  0
653130803Smarcel};
654130803Smarcel
655130803Smarcelconst struct language_defn objc_language_defn = {
656130803Smarcel  "objective-c",		/* Language name */
657130803Smarcel  language_objc,
658130803Smarcel  objc_builtin_types,
659130803Smarcel  range_check_off,
660130803Smarcel  type_check_off,
661130803Smarcel  case_sensitive_on,
662130803Smarcel  &exp_descriptor_standard,
663130803Smarcel  objc_parse,
664130803Smarcel  objc_error,
665130803Smarcel  objc_printchar,		/* Print a character constant */
666130803Smarcel  objc_printstr,		/* Function to print string constant */
667130803Smarcel  objc_emit_char,
668130803Smarcel  objc_create_fundamental_type,	/* Create fundamental type in this language */
669130803Smarcel  c_print_type,			/* Print a type using appropriate syntax */
670130803Smarcel  c_val_print,			/* Print a value using appropriate syntax */
671130803Smarcel  c_value_print,		/* Print a top-level value */
672130803Smarcel  objc_skip_trampoline, 	/* Language specific skip_trampoline */
673130803Smarcel  value_of_this,		/* value_of_this */
674130803Smarcel  basic_lookup_symbol_nonlocal,	/* lookup_symbol_nonlocal */
675130803Smarcel  basic_lookup_transparent_type,/* lookup_transparent_type */
676130803Smarcel  objc_demangle,		/* Language specific symbol demangler */
677130803Smarcel  {"",     "",    "",  ""},	/* Binary format info */
678130803Smarcel  {"0%lo",  "0",   "o", ""},	/* Octal format info */
679130803Smarcel  {"%ld",   "",    "d", ""},	/* Decimal format info */
680130803Smarcel  {"0x%lx", "0x",  "x", ""},	/* Hex format info */
681130803Smarcel  objc_op_print_tab,		/* Expression operators for printing */
682130803Smarcel  1,				/* C-style arrays */
683130803Smarcel  0,				/* String lower bound */
684130803Smarcel  &builtin_type_char,		/* Type of string elements */
685130803Smarcel  default_word_break_characters,
686130803Smarcel  LANG_MAGIC
687130803Smarcel};
688130803Smarcel
689130803Smarcel/*
690130803Smarcel * ObjC:
691130803Smarcel * Following functions help construct Objective-C message calls
692130803Smarcel */
693130803Smarcel
694130803Smarcelstruct selname		/* For parsing Objective-C.  */
695130803Smarcel  {
696130803Smarcel    struct selname *next;
697130803Smarcel    char *msglist_sel;
698130803Smarcel    int msglist_len;
699130803Smarcel  };
700130803Smarcel
701130803Smarcelstatic int msglist_len;
702130803Smarcelstatic struct selname *selname_chain;
703130803Smarcelstatic char *msglist_sel;
704130803Smarcel
705130803Smarcelvoid
706130803Smarcelstart_msglist(void)
707130803Smarcel{
708130803Smarcel  struct selname *new =
709130803Smarcel    (struct selname *) xmalloc (sizeof (struct selname));
710130803Smarcel
711130803Smarcel  new->next = selname_chain;
712130803Smarcel  new->msglist_len = msglist_len;
713130803Smarcel  new->msglist_sel = msglist_sel;
714130803Smarcel  msglist_len = 0;
715130803Smarcel  msglist_sel = (char *)xmalloc(1);
716130803Smarcel  *msglist_sel = 0;
717130803Smarcel  selname_chain = new;
718130803Smarcel}
719130803Smarcel
720130803Smarcelvoid
721130803Smarceladd_msglist(struct stoken *str, int addcolon)
722130803Smarcel{
723130803Smarcel  char *s, *p;
724130803Smarcel  int len, plen;
725130803Smarcel
726130803Smarcel  if (str == 0) {		/* Unnamed arg, or...  */
727130803Smarcel    if (addcolon == 0) {	/* variable number of args.  */
728130803Smarcel      msglist_len++;
729130803Smarcel      return;
730130803Smarcel    }
731130803Smarcel    p = "";
732130803Smarcel    plen = 0;
733130803Smarcel  } else {
734130803Smarcel    p = str->ptr;
735130803Smarcel    plen = str->length;
736130803Smarcel  }
737130803Smarcel  len = plen + strlen(msglist_sel) + 2;
738130803Smarcel  s = (char *)xmalloc(len);
739130803Smarcel  strcpy(s, msglist_sel);
740130803Smarcel  strncat(s, p, plen);
741130803Smarcel  xfree(msglist_sel);
742130803Smarcel  msglist_sel = s;
743130803Smarcel  if (addcolon) {
744130803Smarcel    s[len-2] = ':';
745130803Smarcel    s[len-1] = 0;
746130803Smarcel    msglist_len++;
747130803Smarcel  } else
748130803Smarcel    s[len-2] = '\0';
749130803Smarcel}
750130803Smarcel
751130803Smarcelint
752130803Smarcelend_msglist(void)
753130803Smarcel{
754130803Smarcel  int val = msglist_len;
755130803Smarcel  struct selname *sel = selname_chain;
756130803Smarcel  char *p = msglist_sel;
757130803Smarcel  CORE_ADDR selid;
758130803Smarcel
759130803Smarcel  selname_chain = sel->next;
760130803Smarcel  msglist_len = sel->msglist_len;
761130803Smarcel  msglist_sel = sel->msglist_sel;
762130803Smarcel  selid = lookup_child_selector(p);
763130803Smarcel  if (!selid)
764130803Smarcel    error("Can't find selector \"%s\"", p);
765130803Smarcel  write_exp_elt_longcst (selid);
766130803Smarcel  xfree(p);
767130803Smarcel  write_exp_elt_longcst (val);	/* Number of args */
768130803Smarcel  xfree(sel);
769130803Smarcel
770130803Smarcel  return val;
771130803Smarcel}
772130803Smarcel
773130803Smarcel/*
774130803Smarcel * Function: specialcmp (char *a, char *b)
775130803Smarcel *
776130803Smarcel * Special strcmp: treats ']' and ' ' as end-of-string.
777130803Smarcel * Used for qsorting lists of objc methods (either by class or selector).
778130803Smarcel */
779130803Smarcel
780130803Smarcelstatic int
781130803Smarcelspecialcmp (char *a, char *b)
782130803Smarcel{
783130803Smarcel  while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']')
784130803Smarcel    {
785130803Smarcel      if (*a != *b)
786130803Smarcel	return *a - *b;
787130803Smarcel      a++, b++;
788130803Smarcel    }
789130803Smarcel  if (*a && *a != ' ' && *a != ']')
790130803Smarcel    return  1;		/* a is longer therefore greater */
791130803Smarcel  if (*b && *b != ' ' && *b != ']')
792130803Smarcel    return -1;		/* a is shorter therefore lesser */
793130803Smarcel  return    0;		/* a and b are identical */
794130803Smarcel}
795130803Smarcel
796130803Smarcel/*
797130803Smarcel * Function: compare_selectors (const void *, const void *)
798130803Smarcel *
799130803Smarcel * Comparison function for use with qsort.  Arguments are symbols or
800130803Smarcel * msymbols Compares selector part of objc method name alphabetically.
801130803Smarcel */
802130803Smarcel
803130803Smarcelstatic int
804130803Smarcelcompare_selectors (const void *a, const void *b)
805130803Smarcel{
806130803Smarcel  char *aname, *bname;
807130803Smarcel
808130803Smarcel  aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
809130803Smarcel  bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
810130803Smarcel  if (aname == NULL || bname == NULL)
811130803Smarcel    error ("internal: compare_selectors(1)");
812130803Smarcel
813130803Smarcel  aname = strchr(aname, ' ');
814130803Smarcel  bname = strchr(bname, ' ');
815130803Smarcel  if (aname == NULL || bname == NULL)
816130803Smarcel    error ("internal: compare_selectors(2)");
817130803Smarcel
818130803Smarcel  return specialcmp (aname+1, bname+1);
819130803Smarcel}
820130803Smarcel
821130803Smarcel/*
822130803Smarcel * Function: selectors_info (regexp, from_tty)
823130803Smarcel *
824130803Smarcel * Implements the "Info selectors" command.  Takes an optional regexp
825130803Smarcel * arg.  Lists all objective c selectors that match the regexp.  Works
826130803Smarcel * by grepping thru all symbols for objective c methods.  Output list
827130803Smarcel * is sorted and uniqued.
828130803Smarcel */
829130803Smarcel
830130803Smarcelstatic void
831130803Smarcelselectors_info (char *regexp, int from_tty)
832130803Smarcel{
833130803Smarcel  struct objfile	*objfile;
834130803Smarcel  struct minimal_symbol *msymbol;
835130803Smarcel  char                  *name;
836130803Smarcel  char                  *val;
837130803Smarcel  int                    matches = 0;
838130803Smarcel  int                    maxlen  = 0;
839130803Smarcel  int                    ix;
840130803Smarcel  char                   myregexp[2048];
841130803Smarcel  char                   asel[256];
842130803Smarcel  struct symbol        **sym_arr;
843130803Smarcel  int                    plusminus = 0;
844130803Smarcel
845130803Smarcel  if (regexp == NULL)
846130803Smarcel    strcpy(myregexp, ".*]");	/* Null input, match all objc methods.  */
847130803Smarcel  else
848130803Smarcel    {
849130803Smarcel      if (*regexp == '+' || *regexp == '-')
850130803Smarcel	{ /* User wants only class methods or only instance methods.  */
851130803Smarcel	  plusminus = *regexp++;
852130803Smarcel	  while (*regexp == ' ' || *regexp == '\t')
853130803Smarcel	    regexp++;
854130803Smarcel	}
855130803Smarcel      if (*regexp == '\0')
856130803Smarcel	strcpy(myregexp, ".*]");
857130803Smarcel      else
858130803Smarcel	{
859130803Smarcel	  strcpy(myregexp, regexp);
860130803Smarcel	  if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */
861130803Smarcel	    myregexp[strlen(myregexp) - 1] = ']';    /* end of method name */
862130803Smarcel	  else
863130803Smarcel	    strcat(myregexp, ".*]");
864130803Smarcel	}
865130803Smarcel    }
866130803Smarcel
867130803Smarcel  if (regexp != NULL)
868130803Smarcel    {
869130803Smarcel      val = re_comp (myregexp);
870130803Smarcel      if (val != 0)
871130803Smarcel	error ("Invalid regexp (%s): %s", val, regexp);
872130803Smarcel    }
873130803Smarcel
874130803Smarcel  /* First time thru is JUST to get max length and count.  */
875130803Smarcel  ALL_MSYMBOLS (objfile, msymbol)
876130803Smarcel    {
877130803Smarcel      QUIT;
878130803Smarcel      name = SYMBOL_NATURAL_NAME (msymbol);
879130803Smarcel      if (name &&
880130803Smarcel	 (name[0] == '-' || name[0] == '+') &&
881130803Smarcel	  name[1] == '[')		/* Got a method name.  */
882130803Smarcel	{
883130803Smarcel	  /* Filter for class/instance methods.  */
884130803Smarcel	  if (plusminus && name[0] != plusminus)
885130803Smarcel	    continue;
886130803Smarcel	  /* Find selector part.  */
887130803Smarcel	  name = (char *) strchr(name+2, ' ');
888130803Smarcel	  if (regexp == NULL || re_exec(++name) != 0)
889130803Smarcel	    {
890130803Smarcel	      char *mystart = name;
891130803Smarcel	      char *myend   = (char *) strchr(mystart, ']');
892130803Smarcel
893130803Smarcel	      if (myend && (myend - mystart > maxlen))
894130803Smarcel		maxlen = myend - mystart;	/* Get longest selector.  */
895130803Smarcel	      matches++;
896130803Smarcel	    }
897130803Smarcel	}
898130803Smarcel    }
899130803Smarcel  if (matches)
900130803Smarcel    {
901130803Smarcel      printf_filtered ("Selectors matching \"%s\":\n\n",
902130803Smarcel		       regexp ? regexp : "*");
903130803Smarcel
904130803Smarcel      sym_arr = alloca (matches * sizeof (struct symbol *));
905130803Smarcel      matches = 0;
906130803Smarcel      ALL_MSYMBOLS (objfile, msymbol)
907130803Smarcel	{
908130803Smarcel	  QUIT;
909130803Smarcel	  name = SYMBOL_NATURAL_NAME (msymbol);
910130803Smarcel	  if (name &&
911130803Smarcel	     (name[0] == '-' || name[0] == '+') &&
912130803Smarcel	      name[1] == '[')		/* Got a method name.  */
913130803Smarcel	    {
914130803Smarcel	      /* Filter for class/instance methods.  */
915130803Smarcel	      if (plusminus && name[0] != plusminus)
916130803Smarcel		continue;
917130803Smarcel	      /* Find selector part.  */
918130803Smarcel	      name = (char *) strchr(name+2, ' ');
919130803Smarcel	      if (regexp == NULL || re_exec(++name) != 0)
920130803Smarcel		sym_arr[matches++] = (struct symbol *) msymbol;
921130803Smarcel	    }
922130803Smarcel	}
923130803Smarcel
924130803Smarcel      qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
925130803Smarcel	     compare_selectors);
926130803Smarcel      /* Prevent compare on first iteration.  */
927130803Smarcel      asel[0] = 0;
928130803Smarcel      for (ix = 0; ix < matches; ix++)	/* Now do the output.  */
929130803Smarcel	{
930130803Smarcel	  char *p = asel;
931130803Smarcel
932130803Smarcel	  QUIT;
933130803Smarcel	  name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
934130803Smarcel	  name = strchr (name, ' ') + 1;
935130803Smarcel	  if (p[0] && specialcmp(name, p) == 0)
936130803Smarcel	    continue;		/* Seen this one already (not unique).  */
937130803Smarcel
938130803Smarcel	  /* Copy selector part.  */
939130803Smarcel	  while (*name && *name != ']')
940130803Smarcel	    *p++ = *name++;
941130803Smarcel	  *p++ = '\0';
942130803Smarcel	  /* Print in columns.  */
943130803Smarcel	  puts_filtered_tabular(asel, maxlen + 1, 0);
944130803Smarcel	}
945130803Smarcel      begin_line();
946130803Smarcel    }
947130803Smarcel  else
948130803Smarcel    printf_filtered ("No selectors matching \"%s\"\n", regexp ? regexp : "*");
949130803Smarcel}
950130803Smarcel
951130803Smarcel/*
952130803Smarcel * Function: compare_classes (const void *, const void *)
953130803Smarcel *
954130803Smarcel * Comparison function for use with qsort.  Arguments are symbols or
955130803Smarcel * msymbols Compares class part of objc method name alphabetically.
956130803Smarcel */
957130803Smarcel
958130803Smarcelstatic int
959130803Smarcelcompare_classes (const void *a, const void *b)
960130803Smarcel{
961130803Smarcel  char *aname, *bname;
962130803Smarcel
963130803Smarcel  aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
964130803Smarcel  bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
965130803Smarcel  if (aname == NULL || bname == NULL)
966130803Smarcel    error ("internal: compare_classes(1)");
967130803Smarcel
968130803Smarcel  return specialcmp (aname+1, bname+1);
969130803Smarcel}
970130803Smarcel
971130803Smarcel/*
972130803Smarcel * Function: classes_info(regexp, from_tty)
973130803Smarcel *
974130803Smarcel * Implements the "info classes" command for objective c classes.
975130803Smarcel * Lists all objective c classes that match the optional regexp.
976130803Smarcel * Works by grepping thru the list of objective c methods.  List will
977130803Smarcel * be sorted and uniqued (since one class may have many methods).
978130803Smarcel * BUGS: will not list a class that has no methods.
979130803Smarcel */
980130803Smarcel
981130803Smarcelstatic void
982130803Smarcelclasses_info (char *regexp, int from_tty)
983130803Smarcel{
984130803Smarcel  struct objfile	*objfile;
985130803Smarcel  struct minimal_symbol *msymbol;
986130803Smarcel  char                  *name;
987130803Smarcel  char                  *val;
988130803Smarcel  int                    matches = 0;
989130803Smarcel  int                    maxlen  = 0;
990130803Smarcel  int                    ix;
991130803Smarcel  char                   myregexp[2048];
992130803Smarcel  char                   aclass[256];
993130803Smarcel  struct symbol        **sym_arr;
994130803Smarcel
995130803Smarcel  if (regexp == NULL)
996130803Smarcel    strcpy(myregexp, ".* ");	/* Null input: match all objc classes.  */
997130803Smarcel  else
998130803Smarcel    {
999130803Smarcel      strcpy(myregexp, regexp);
1000130803Smarcel      if (myregexp[strlen(myregexp) - 1] == '$')
1001130803Smarcel	/* In the method name, the end of the class name is marked by ' '.  */
1002130803Smarcel	myregexp[strlen(myregexp) - 1] = ' ';
1003130803Smarcel      else
1004130803Smarcel	strcat(myregexp, ".* ");
1005130803Smarcel    }
1006130803Smarcel
1007130803Smarcel  if (regexp != NULL)
1008130803Smarcel    {
1009130803Smarcel      val = re_comp (myregexp);
1010130803Smarcel      if (val != 0)
1011130803Smarcel	error ("Invalid regexp (%s): %s", val, regexp);
1012130803Smarcel    }
1013130803Smarcel
1014130803Smarcel  /* First time thru is JUST to get max length and count.  */
1015130803Smarcel  ALL_MSYMBOLS (objfile, msymbol)
1016130803Smarcel    {
1017130803Smarcel      QUIT;
1018130803Smarcel      name = SYMBOL_NATURAL_NAME (msymbol);
1019130803Smarcel      if (name &&
1020130803Smarcel	 (name[0] == '-' || name[0] == '+') &&
1021130803Smarcel	  name[1] == '[')			/* Got a method name.  */
1022130803Smarcel	if (regexp == NULL || re_exec(name+2) != 0)
1023130803Smarcel	  {
1024130803Smarcel	    /* Compute length of classname part.  */
1025130803Smarcel	    char *mystart = name + 2;
1026130803Smarcel	    char *myend   = (char *) strchr(mystart, ' ');
1027130803Smarcel
1028130803Smarcel	    if (myend && (myend - mystart > maxlen))
1029130803Smarcel	      maxlen = myend - mystart;
1030130803Smarcel	    matches++;
1031130803Smarcel	  }
1032130803Smarcel    }
1033130803Smarcel  if (matches)
1034130803Smarcel    {
1035130803Smarcel      printf_filtered ("Classes matching \"%s\":\n\n",
1036130803Smarcel		       regexp ? regexp : "*");
1037130803Smarcel      sym_arr = alloca (matches * sizeof (struct symbol *));
1038130803Smarcel      matches = 0;
1039130803Smarcel      ALL_MSYMBOLS (objfile, msymbol)
1040130803Smarcel	{
1041130803Smarcel	  QUIT;
1042130803Smarcel	  name = SYMBOL_NATURAL_NAME (msymbol);
1043130803Smarcel	  if (name &&
1044130803Smarcel	     (name[0] == '-' || name[0] == '+') &&
1045130803Smarcel	      name[1] == '[')			/* Got a method name.  */
1046130803Smarcel	    if (regexp == NULL || re_exec(name+2) != 0)
1047130803Smarcel		sym_arr[matches++] = (struct symbol *) msymbol;
1048130803Smarcel	}
1049130803Smarcel
1050130803Smarcel      qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
1051130803Smarcel	     compare_classes);
1052130803Smarcel      /* Prevent compare on first iteration.  */
1053130803Smarcel      aclass[0] = 0;
1054130803Smarcel      for (ix = 0; ix < matches; ix++)	/* Now do the output.  */
1055130803Smarcel	{
1056130803Smarcel	  char *p = aclass;
1057130803Smarcel
1058130803Smarcel	  QUIT;
1059130803Smarcel	  name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
1060130803Smarcel	  name += 2;
1061130803Smarcel	  if (p[0] && specialcmp(name, p) == 0)
1062130803Smarcel	    continue;	/* Seen this one already (not unique).  */
1063130803Smarcel
1064130803Smarcel	  /* Copy class part of method name.  */
1065130803Smarcel	  while (*name && *name != ' ')
1066130803Smarcel	    *p++ = *name++;
1067130803Smarcel	  *p++ = '\0';
1068130803Smarcel	  /* Print in columns.  */
1069130803Smarcel	  puts_filtered_tabular(aclass, maxlen + 1, 0);
1070130803Smarcel	}
1071130803Smarcel      begin_line();
1072130803Smarcel    }
1073130803Smarcel  else
1074130803Smarcel    printf_filtered ("No classes matching \"%s\"\n", regexp ? regexp : "*");
1075130803Smarcel}
1076130803Smarcel
1077130803Smarcel/*
1078130803Smarcel * Function: find_imps (char *selector, struct symbol **sym_arr)
1079130803Smarcel *
1080130803Smarcel * Input:  a string representing a selector
1081130803Smarcel *         a pointer to an array of symbol pointers
1082130803Smarcel *         possibly a pointer to a symbol found by the caller.
1083130803Smarcel *
1084130803Smarcel * Output: number of methods that implement that selector.  Side
1085130803Smarcel * effects: The array of symbol pointers is filled with matching syms.
1086130803Smarcel *
1087130803Smarcel * By analogy with function "find_methods" (symtab.c), builds a list
1088130803Smarcel * of symbols matching the ambiguous input, so that "decode_line_2"
1089130803Smarcel * (symtab.c) can list them and ask the user to choose one or more.
1090130803Smarcel * In this case the matches are objective c methods
1091130803Smarcel * ("implementations") matching an objective c selector.
1092130803Smarcel *
1093130803Smarcel * Note that it is possible for a normal (c-style) function to have
1094130803Smarcel * the same name as an objective c selector.  To prevent the selector
1095130803Smarcel * from eclipsing the function, we allow the caller (decode_line_1) to
1096130803Smarcel * search for such a function first, and if it finds one, pass it in
1097130803Smarcel * to us.  We will then integrate it into the list.  We also search
1098130803Smarcel * for one here, among the minsyms.
1099130803Smarcel *
1100130803Smarcel * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
1101130803Smarcel *       into two parts: debuggable (struct symbol) syms, and
1102130803Smarcel *       non_debuggable (struct minimal_symbol) syms.  The debuggable
1103130803Smarcel *       ones will come first, before NUM_DEBUGGABLE (which will thus
1104130803Smarcel *       be the index of the first non-debuggable one).
1105130803Smarcel */
1106130803Smarcel
1107130803Smarcel/*
1108130803Smarcel * Function: total_number_of_imps (char *selector);
1109130803Smarcel *
1110130803Smarcel * Input:  a string representing a selector
1111130803Smarcel * Output: number of methods that implement that selector.
1112130803Smarcel *
1113130803Smarcel * By analogy with function "total_number_of_methods", this allows
1114130803Smarcel * decode_line_1 (symtab.c) to detect if there are objective c methods
1115130803Smarcel * matching the input, and to allocate an array of pointers to them
1116130803Smarcel * which can be manipulated by "decode_line_2" (also in symtab.c).
1117130803Smarcel */
1118130803Smarcel
1119130803Smarcelchar *
1120130803Smarcelparse_selector (char *method, char **selector)
1121130803Smarcel{
1122130803Smarcel  char *s1 = NULL;
1123130803Smarcel  char *s2 = NULL;
1124130803Smarcel  int found_quote = 0;
1125130803Smarcel
1126130803Smarcel  char *nselector = NULL;
1127130803Smarcel
1128130803Smarcel  gdb_assert (selector != NULL);
1129130803Smarcel
1130130803Smarcel  s1 = method;
1131130803Smarcel
1132130803Smarcel  while (isspace (*s1))
1133130803Smarcel    s1++;
1134130803Smarcel  if (*s1 == '\'')
1135130803Smarcel    {
1136130803Smarcel      found_quote = 1;
1137130803Smarcel      s1++;
1138130803Smarcel    }
1139130803Smarcel  while (isspace (*s1))
1140130803Smarcel    s1++;
1141130803Smarcel
1142130803Smarcel  nselector = s1;
1143130803Smarcel  s2 = s1;
1144130803Smarcel
1145130803Smarcel  for (;;) {
1146130803Smarcel    if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
1147130803Smarcel      *s1++ = *s2;
1148130803Smarcel    else if (isspace (*s2))
1149130803Smarcel      ;
1150130803Smarcel    else if ((*s2 == '\0') || (*s2 == '\''))
1151130803Smarcel      break;
1152130803Smarcel    else
1153130803Smarcel      return NULL;
1154130803Smarcel    s2++;
1155130803Smarcel  }
1156130803Smarcel  *s1++ = '\0';
1157130803Smarcel
1158130803Smarcel  while (isspace (*s2))
1159130803Smarcel    s2++;
1160130803Smarcel  if (found_quote)
1161130803Smarcel    {
1162130803Smarcel      if (*s2 == '\'')
1163130803Smarcel	s2++;
1164130803Smarcel      while (isspace (*s2))
1165130803Smarcel	s2++;
1166130803Smarcel    }
1167130803Smarcel
1168130803Smarcel  if (selector != NULL)
1169130803Smarcel    *selector = nselector;
1170130803Smarcel
1171130803Smarcel  return s2;
1172130803Smarcel}
1173130803Smarcel
1174130803Smarcelchar *
1175130803Smarcelparse_method (char *method, char *type, char **class,
1176130803Smarcel	      char **category, char **selector)
1177130803Smarcel{
1178130803Smarcel  char *s1 = NULL;
1179130803Smarcel  char *s2 = NULL;
1180130803Smarcel  int found_quote = 0;
1181130803Smarcel
1182130803Smarcel  char ntype = '\0';
1183130803Smarcel  char *nclass = NULL;
1184130803Smarcel  char *ncategory = NULL;
1185130803Smarcel  char *nselector = NULL;
1186130803Smarcel
1187130803Smarcel  gdb_assert (type != NULL);
1188130803Smarcel  gdb_assert (class != NULL);
1189130803Smarcel  gdb_assert (category != NULL);
1190130803Smarcel  gdb_assert (selector != NULL);
1191130803Smarcel
1192130803Smarcel  s1 = method;
1193130803Smarcel
1194130803Smarcel  while (isspace (*s1))
1195130803Smarcel    s1++;
1196130803Smarcel  if (*s1 == '\'')
1197130803Smarcel    {
1198130803Smarcel      found_quote = 1;
1199130803Smarcel      s1++;
1200130803Smarcel    }
1201130803Smarcel  while (isspace (*s1))
1202130803Smarcel    s1++;
1203130803Smarcel
1204130803Smarcel  if ((s1[0] == '+') || (s1[0] == '-'))
1205130803Smarcel    ntype = *s1++;
1206130803Smarcel
1207130803Smarcel  while (isspace (*s1))
1208130803Smarcel    s1++;
1209130803Smarcel
1210130803Smarcel  if (*s1 != '[')
1211130803Smarcel    return NULL;
1212130803Smarcel  s1++;
1213130803Smarcel
1214130803Smarcel  nclass = s1;
1215130803Smarcel  while (isalnum (*s1) || (*s1 == '_'))
1216130803Smarcel    s1++;
1217130803Smarcel
1218130803Smarcel  s2 = s1;
1219130803Smarcel  while (isspace (*s2))
1220130803Smarcel    s2++;
1221130803Smarcel
1222130803Smarcel  if (*s2 == '(')
1223130803Smarcel    {
1224130803Smarcel      s2++;
1225130803Smarcel      while (isspace (*s2))
1226130803Smarcel	s2++;
1227130803Smarcel      ncategory = s2;
1228130803Smarcel      while (isalnum (*s2) || (*s2 == '_'))
1229130803Smarcel	s2++;
1230130803Smarcel      *s2++ = '\0';
1231130803Smarcel    }
1232130803Smarcel
1233130803Smarcel  /* Truncate the class name now that we're not using the open paren.  */
1234130803Smarcel  *s1++ = '\0';
1235130803Smarcel
1236130803Smarcel  nselector = s2;
1237130803Smarcel  s1 = s2;
1238130803Smarcel
1239130803Smarcel  for (;;) {
1240130803Smarcel    if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
1241130803Smarcel      *s1++ = *s2;
1242130803Smarcel    else if (isspace (*s2))
1243130803Smarcel      ;
1244130803Smarcel    else if (*s2 == ']')
1245130803Smarcel      break;
1246130803Smarcel    else
1247130803Smarcel      return NULL;
1248130803Smarcel    s2++;
1249130803Smarcel  }
1250130803Smarcel  *s1++ = '\0';
1251130803Smarcel  s2++;
1252130803Smarcel
1253130803Smarcel  while (isspace (*s2))
1254130803Smarcel    s2++;
1255130803Smarcel  if (found_quote)
1256130803Smarcel    {
1257130803Smarcel      if (*s2 != '\'')
1258130803Smarcel	return NULL;
1259130803Smarcel      s2++;
1260130803Smarcel      while (isspace (*s2))
1261130803Smarcel	s2++;
1262130803Smarcel    }
1263130803Smarcel
1264130803Smarcel  if (type != NULL)
1265130803Smarcel    *type = ntype;
1266130803Smarcel  if (class != NULL)
1267130803Smarcel    *class = nclass;
1268130803Smarcel  if (category != NULL)
1269130803Smarcel    *category = ncategory;
1270130803Smarcel  if (selector != NULL)
1271130803Smarcel    *selector = nselector;
1272130803Smarcel
1273130803Smarcel  return s2;
1274130803Smarcel}
1275130803Smarcel
1276130803Smarcelstatic void
1277130803Smarcelfind_methods (struct symtab *symtab, char type,
1278130803Smarcel	      const char *class, const char *category,
1279130803Smarcel	      const char *selector, struct symbol **syms,
1280130803Smarcel	      unsigned int *nsym, unsigned int *ndebug)
1281130803Smarcel{
1282130803Smarcel  struct objfile *objfile = NULL;
1283130803Smarcel  struct minimal_symbol *msymbol = NULL;
1284130803Smarcel  struct block *block = NULL;
1285130803Smarcel  struct symbol *sym = NULL;
1286130803Smarcel
1287130803Smarcel  char *symname = NULL;
1288130803Smarcel
1289130803Smarcel  char ntype = '\0';
1290130803Smarcel  char *nclass = NULL;
1291130803Smarcel  char *ncategory = NULL;
1292130803Smarcel  char *nselector = NULL;
1293130803Smarcel
1294130803Smarcel  unsigned int csym = 0;
1295130803Smarcel  unsigned int cdebug = 0;
1296130803Smarcel
1297130803Smarcel  static char *tmp = NULL;
1298130803Smarcel  static unsigned int tmplen = 0;
1299130803Smarcel
1300130803Smarcel  gdb_assert (nsym != NULL);
1301130803Smarcel  gdb_assert (ndebug != NULL);
1302130803Smarcel
1303130803Smarcel  if (symtab)
1304130803Smarcel    block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
1305130803Smarcel
1306130803Smarcel  ALL_MSYMBOLS (objfile, msymbol)
1307130803Smarcel    {
1308130803Smarcel      QUIT;
1309130803Smarcel
1310130803Smarcel      if ((msymbol->type != mst_text) && (msymbol->type != mst_file_text))
1311130803Smarcel	/* Not a function or method.  */
1312130803Smarcel	continue;
1313130803Smarcel
1314130803Smarcel      if (symtab)
1315130803Smarcel	if ((SYMBOL_VALUE_ADDRESS (msymbol) <  BLOCK_START (block)) ||
1316130803Smarcel	    (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block)))
1317130803Smarcel	  /* Not in the specified symtab.  */
1318130803Smarcel	  continue;
1319130803Smarcel
1320130803Smarcel      symname = SYMBOL_NATURAL_NAME (msymbol);
1321130803Smarcel      if (symname == NULL)
1322130803Smarcel	continue;
1323130803Smarcel
1324130803Smarcel      if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '['))
1325130803Smarcel	/* Not a method name.  */
1326130803Smarcel	continue;
1327130803Smarcel
1328130803Smarcel      while ((strlen (symname) + 1) >= tmplen)
1329130803Smarcel	{
1330130803Smarcel	  tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
1331130803Smarcel	  tmp = xrealloc (tmp, tmplen);
1332130803Smarcel	}
1333130803Smarcel      strcpy (tmp, symname);
1334130803Smarcel
1335130803Smarcel      if (parse_method (tmp, &ntype, &nclass, &ncategory, &nselector) == NULL)
1336130803Smarcel	continue;
1337130803Smarcel
1338130803Smarcel      if ((type != '\0') && (ntype != type))
1339130803Smarcel	continue;
1340130803Smarcel
1341130803Smarcel      if ((class != NULL)
1342130803Smarcel	  && ((nclass == NULL) || (strcmp (class, nclass) != 0)))
1343130803Smarcel	continue;
1344130803Smarcel
1345130803Smarcel      if ((category != NULL) &&
1346130803Smarcel	  ((ncategory == NULL) || (strcmp (category, ncategory) != 0)))
1347130803Smarcel	continue;
1348130803Smarcel
1349130803Smarcel      if ((selector != NULL) &&
1350130803Smarcel	  ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
1351130803Smarcel	continue;
1352130803Smarcel
1353130803Smarcel      sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
1354130803Smarcel      if (sym != NULL)
1355130803Smarcel        {
1356130803Smarcel          const char *newsymname = SYMBOL_NATURAL_NAME (sym);
1357130803Smarcel
1358130803Smarcel          if (strcmp (symname, newsymname) == 0)
1359130803Smarcel            {
1360130803Smarcel              /* Found a high-level method sym: swap it into the
1361130803Smarcel                 lower part of sym_arr (below num_debuggable).  */
1362130803Smarcel              if (syms != NULL)
1363130803Smarcel                {
1364130803Smarcel                  syms[csym] = syms[cdebug];
1365130803Smarcel                  syms[cdebug] = sym;
1366130803Smarcel                }
1367130803Smarcel              csym++;
1368130803Smarcel              cdebug++;
1369130803Smarcel            }
1370130803Smarcel          else
1371130803Smarcel            {
1372130803Smarcel              warning (
1373130803Smarcel"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring",
1374130803Smarcel                       newsymname, symname);
1375130803Smarcel              if (syms != NULL)
1376130803Smarcel                syms[csym] = (struct symbol *) msymbol;
1377130803Smarcel              csym++;
1378130803Smarcel            }
1379130803Smarcel        }
1380130803Smarcel      else
1381130803Smarcel	{
1382130803Smarcel	  /* Found a non-debuggable method symbol.  */
1383130803Smarcel	  if (syms != NULL)
1384130803Smarcel	    syms[csym] = (struct symbol *) msymbol;
1385130803Smarcel	  csym++;
1386130803Smarcel	}
1387130803Smarcel    }
1388130803Smarcel
1389130803Smarcel  if (nsym != NULL)
1390130803Smarcel    *nsym = csym;
1391130803Smarcel  if (ndebug != NULL)
1392130803Smarcel    *ndebug = cdebug;
1393130803Smarcel}
1394130803Smarcel
1395130803Smarcelchar *find_imps (struct symtab *symtab, struct block *block,
1396130803Smarcel		 char *method, struct symbol **syms,
1397130803Smarcel		 unsigned int *nsym, unsigned int *ndebug)
1398130803Smarcel{
1399130803Smarcel  char type = '\0';
1400130803Smarcel  char *class = NULL;
1401130803Smarcel  char *category = NULL;
1402130803Smarcel  char *selector = NULL;
1403130803Smarcel
1404130803Smarcel  unsigned int csym = 0;
1405130803Smarcel  unsigned int cdebug = 0;
1406130803Smarcel
1407130803Smarcel  unsigned int ncsym = 0;
1408130803Smarcel  unsigned int ncdebug = 0;
1409130803Smarcel
1410130803Smarcel  char *buf = NULL;
1411130803Smarcel  char *tmp = NULL;
1412130803Smarcel
1413130803Smarcel  gdb_assert (nsym != NULL);
1414130803Smarcel  gdb_assert (ndebug != NULL);
1415130803Smarcel
1416130803Smarcel  if (nsym != NULL)
1417130803Smarcel    *nsym = 0;
1418130803Smarcel  if (ndebug != NULL)
1419130803Smarcel    *ndebug = 0;
1420130803Smarcel
1421130803Smarcel  buf = (char *) alloca (strlen (method) + 1);
1422130803Smarcel  strcpy (buf, method);
1423130803Smarcel  tmp = parse_method (buf, &type, &class, &category, &selector);
1424130803Smarcel
1425130803Smarcel  if (tmp == NULL) {
1426130803Smarcel
1427130803Smarcel    struct symbol *sym = NULL;
1428130803Smarcel    struct minimal_symbol *msym = NULL;
1429130803Smarcel
1430130803Smarcel    strcpy (buf, method);
1431130803Smarcel    tmp = parse_selector (buf, &selector);
1432130803Smarcel
1433130803Smarcel    if (tmp == NULL)
1434130803Smarcel      return NULL;
1435130803Smarcel
1436130803Smarcel    sym = lookup_symbol (selector, block, VAR_DOMAIN, 0, NULL);
1437130803Smarcel    if (sym != NULL)
1438130803Smarcel      {
1439130803Smarcel	if (syms)
1440130803Smarcel	  syms[csym] = sym;
1441130803Smarcel	csym++;
1442130803Smarcel	cdebug++;
1443130803Smarcel      }
1444130803Smarcel
1445130803Smarcel    if (sym == NULL)
1446130803Smarcel      msym = lookup_minimal_symbol (selector, 0, 0);
1447130803Smarcel
1448130803Smarcel    if (msym != NULL)
1449130803Smarcel      {
1450130803Smarcel	if (syms)
1451130803Smarcel	  syms[csym] = (struct symbol *)msym;
1452130803Smarcel	csym++;
1453130803Smarcel      }
1454130803Smarcel  }
1455130803Smarcel
1456130803Smarcel  if (syms != NULL)
1457130803Smarcel    find_methods (symtab, type, class, category, selector,
1458130803Smarcel		  syms + csym, &ncsym, &ncdebug);
1459130803Smarcel  else
1460130803Smarcel    find_methods (symtab, type, class, category, selector,
1461130803Smarcel		  NULL, &ncsym, &ncdebug);
1462130803Smarcel
1463130803Smarcel  /* If we didn't find any methods, just return.  */
1464130803Smarcel  if (ncsym == 0 && ncdebug == 0)
1465130803Smarcel    return method;
1466130803Smarcel
1467130803Smarcel  /* Take debug symbols from the second batch of symbols and swap them
1468130803Smarcel   * with debug symbols from the first batch.  Repeat until either the
1469130803Smarcel   * second section is out of debug symbols or the first section is
1470130803Smarcel   * full of debug symbols.  Either way we have all debug symbols
1471130803Smarcel   * packed to the beginning of the buffer.
1472130803Smarcel   */
1473130803Smarcel
1474130803Smarcel  if (syms != NULL)
1475130803Smarcel    {
1476130803Smarcel      while ((cdebug < csym) && (ncdebug > 0))
1477130803Smarcel	{
1478130803Smarcel	  struct symbol *s = NULL;
1479130803Smarcel	  /* First non-debugging symbol.  */
1480130803Smarcel	  unsigned int i = cdebug;
1481130803Smarcel	  /* Last of second batch of debug symbols.  */
1482130803Smarcel	  unsigned int j = csym + ncdebug - 1;
1483130803Smarcel
1484130803Smarcel	  s = syms[j];
1485130803Smarcel	  syms[j] = syms[i];
1486130803Smarcel	  syms[i] = s;
1487130803Smarcel
1488130803Smarcel	  /* We've moved a symbol from the second debug section to the
1489130803Smarcel             first one.  */
1490130803Smarcel	  cdebug++;
1491130803Smarcel	  ncdebug--;
1492130803Smarcel	}
1493130803Smarcel    }
1494130803Smarcel
1495130803Smarcel  csym += ncsym;
1496130803Smarcel  cdebug += ncdebug;
1497130803Smarcel
1498130803Smarcel  if (nsym != NULL)
1499130803Smarcel    *nsym = csym;
1500130803Smarcel  if (ndebug != NULL)
1501130803Smarcel    *ndebug = cdebug;
1502130803Smarcel
1503130803Smarcel  if (syms == NULL)
1504130803Smarcel    return method + (tmp - buf);
1505130803Smarcel
1506130803Smarcel  if (csym > 1)
1507130803Smarcel    {
1508130803Smarcel      /* Sort debuggable symbols.  */
1509130803Smarcel      if (cdebug > 1)
1510130803Smarcel	qsort (syms, cdebug, sizeof (struct minimal_symbol *),
1511130803Smarcel	       compare_classes);
1512130803Smarcel
1513130803Smarcel      /* Sort minimal_symbols.  */
1514130803Smarcel      if ((csym - cdebug) > 1)
1515130803Smarcel	qsort (&syms[cdebug], csym - cdebug,
1516130803Smarcel	       sizeof (struct minimal_symbol *), compare_classes);
1517130803Smarcel    }
1518130803Smarcel  /* Terminate the sym_arr list.  */
1519130803Smarcel  syms[csym] = 0;
1520130803Smarcel
1521130803Smarcel  return method + (tmp - buf);
1522130803Smarcel}
1523130803Smarcel
1524130803Smarcelstatic void
1525130803Smarcelprint_object_command (char *args, int from_tty)
1526130803Smarcel{
1527130803Smarcel  struct value *object, *function, *description;
1528130803Smarcel  CORE_ADDR string_addr, object_addr;
1529130803Smarcel  int i = 0;
1530130803Smarcel  char c = -1;
1531130803Smarcel
1532130803Smarcel  if (!args || !*args)
1533130803Smarcel    error (
1534130803Smarcel"The 'print-object' command requires an argument (an Objective-C object)");
1535130803Smarcel
1536130803Smarcel  {
1537130803Smarcel    struct expression *expr = parse_expression (args);
1538130803Smarcel    struct cleanup *old_chain =
1539130803Smarcel      make_cleanup (free_current_contents, &expr);
1540130803Smarcel    int pc = 0;
1541130803Smarcel
1542130803Smarcel    object = expr->language_defn->la_exp_desc->evaluate_exp
1543130803Smarcel      (builtin_type_void_data_ptr, expr, &pc, EVAL_NORMAL);
1544130803Smarcel    do_cleanups (old_chain);
1545130803Smarcel  }
1546130803Smarcel
1547130803Smarcel  /* Validate the address for sanity.  */
1548130803Smarcel  object_addr = value_as_long (object);
1549130803Smarcel  read_memory (object_addr, &c, 1);
1550130803Smarcel
1551130803Smarcel  function = find_function_in_inferior ("_NSPrintForDebugger");
1552130803Smarcel  if (function == NULL)
1553130803Smarcel    error ("Unable to locate _NSPrintForDebugger in child process");
1554130803Smarcel
1555130803Smarcel  description = call_function_by_hand (function, 1, &object);
1556130803Smarcel
1557130803Smarcel  string_addr = value_as_long (description);
1558130803Smarcel  if (string_addr == 0)
1559130803Smarcel    error ("object returns null description");
1560130803Smarcel
1561130803Smarcel  read_memory (string_addr + i++, &c, 1);
1562130803Smarcel  if (c != '\0')
1563130803Smarcel    do
1564130803Smarcel      { /* Read and print characters up to EOS.  */
1565130803Smarcel	QUIT;
1566130803Smarcel	printf_filtered ("%c", c);
1567130803Smarcel	read_memory (string_addr + i++, &c, 1);
1568130803Smarcel      } while (c != 0);
1569130803Smarcel  else
1570130803Smarcel    printf_filtered("<object returns empty description>");
1571130803Smarcel  printf_filtered ("\n");
1572130803Smarcel}
1573130803Smarcel
1574130803Smarcel/* The data structure 'methcalls' is used to detect method calls (thru
1575130803Smarcel * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.),
1576130803Smarcel * and ultimately find the method being called.
1577130803Smarcel */
1578130803Smarcel
1579130803Smarcelstruct objc_methcall {
1580130803Smarcel  char *name;
1581130803Smarcel /* Return instance method to be called.  */
1582130803Smarcel  int (*stop_at) (CORE_ADDR, CORE_ADDR *);
1583130803Smarcel  /* Start of pc range corresponding to method invocation.  */
1584130803Smarcel  CORE_ADDR begin;
1585130803Smarcel  /* End of pc range corresponding to method invocation.  */
1586130803Smarcel  CORE_ADDR end;
1587130803Smarcel};
1588130803Smarcel
1589130803Smarcelstatic int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc);
1590130803Smarcelstatic int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
1591130803Smarcelstatic int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc);
1592130803Smarcelstatic int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
1593130803Smarcel
1594130803Smarcelstatic struct objc_methcall methcalls[] = {
1595130803Smarcel  { "_objc_msgSend", resolve_msgsend, 0, 0},
1596130803Smarcel  { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0},
1597130803Smarcel  { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0},
1598130803Smarcel  { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0},
1599130803Smarcel  { "_objc_getClass", NULL, 0, 0},
1600130803Smarcel  { "_objc_getMetaClass", NULL, 0, 0}
1601130803Smarcel};
1602130803Smarcel
1603130803Smarcel#define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0]))
1604130803Smarcel
1605130803Smarcel/* The following function, "find_objc_msgsend", fills in the data
1606130803Smarcel * structure "objc_msgs" by finding the addresses of each of the
1607130803Smarcel * (currently four) functions that it holds (of which objc_msgSend is
1608130803Smarcel * the first).  This must be called each time symbols are loaded, in
1609130803Smarcel * case the functions have moved for some reason.
1610130803Smarcel */
1611130803Smarcel
1612130803Smarcelstatic void
1613130803Smarcelfind_objc_msgsend (void)
1614130803Smarcel{
1615130803Smarcel  unsigned int i;
1616130803Smarcel  for (i = 0; i < nmethcalls; i++) {
1617130803Smarcel
1618130803Smarcel    struct minimal_symbol *func;
1619130803Smarcel
1620130803Smarcel    /* Try both with and without underscore.  */
1621130803Smarcel    func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL);
1622130803Smarcel    if ((func == NULL) && (methcalls[i].name[0] == '_')) {
1623130803Smarcel      func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL);
1624130803Smarcel    }
1625130803Smarcel    if (func == NULL) {
1626130803Smarcel      methcalls[i].begin = 0;
1627130803Smarcel      methcalls[i].end = 0;
1628130803Smarcel      continue;
1629130803Smarcel    }
1630130803Smarcel
1631130803Smarcel    methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func);
1632130803Smarcel    do {
1633130803Smarcel      methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func);
1634130803Smarcel    } while (methcalls[i].begin == methcalls[i].end);
1635130803Smarcel  }
1636130803Smarcel}
1637130803Smarcel
1638130803Smarcel/* find_objc_msgcall (replaces pc_off_limits)
1639130803Smarcel *
1640130803Smarcel * ALL that this function now does is to determine whether the input
1641130803Smarcel * address ("pc") is the address of one of the Objective-C message
1642130803Smarcel * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and
1643130803Smarcel * if so, it returns the address of the method that will be called.
1644130803Smarcel *
1645130803Smarcel * The old function "pc_off_limits" used to do a lot of other things
1646130803Smarcel * in addition, such as detecting shared library jump stubs and
1647130803Smarcel * returning the address of the shlib function that would be called.
1648130803Smarcel * That functionality has been moved into the SKIP_TRAMPOLINE_CODE and
1649130803Smarcel * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target-
1650130803Smarcel * dependent modules.
1651130803Smarcel */
1652130803Smarcel
1653130803Smarcelstruct objc_submethod_helper_data {
1654130803Smarcel  int (*f) (CORE_ADDR, CORE_ADDR *);
1655130803Smarcel  CORE_ADDR pc;
1656130803Smarcel  CORE_ADDR *new_pc;
1657130803Smarcel};
1658130803Smarcel
1659130803Smarcelstatic int
1660130803Smarcelfind_objc_msgcall_submethod_helper (void * arg)
1661130803Smarcel{
1662130803Smarcel  struct objc_submethod_helper_data *s =
1663130803Smarcel    (struct objc_submethod_helper_data *) arg;
1664130803Smarcel
1665130803Smarcel  if (s->f (s->pc, s->new_pc) == 0)
1666130803Smarcel    return 1;
1667130803Smarcel  else
1668130803Smarcel    return 0;
1669130803Smarcel}
1670130803Smarcel
1671130803Smarcelstatic int
1672130803Smarcelfind_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
1673130803Smarcel			     CORE_ADDR pc,
1674130803Smarcel			     CORE_ADDR *new_pc)
1675130803Smarcel{
1676130803Smarcel  struct objc_submethod_helper_data s;
1677130803Smarcel
1678130803Smarcel  s.f = f;
1679130803Smarcel  s.pc = pc;
1680130803Smarcel  s.new_pc = new_pc;
1681130803Smarcel
1682130803Smarcel  if (catch_errors (find_objc_msgcall_submethod_helper,
1683130803Smarcel		    (void *) &s,
1684130803Smarcel		    "Unable to determine target of Objective-C method call (ignoring):\n",
1685130803Smarcel		    RETURN_MASK_ALL) == 0)
1686130803Smarcel    return 1;
1687130803Smarcel  else
1688130803Smarcel    return 0;
1689130803Smarcel}
1690130803Smarcel
1691130803Smarcelint
1692130803Smarcelfind_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
1693130803Smarcel{
1694130803Smarcel  unsigned int i;
1695130803Smarcel
1696130803Smarcel  find_objc_msgsend ();
1697130803Smarcel  if (new_pc != NULL)
1698130803Smarcel    {
1699130803Smarcel      *new_pc = 0;
1700130803Smarcel    }
1701130803Smarcel
1702130803Smarcel  for (i = 0; i < nmethcalls; i++)
1703130803Smarcel    if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end))
1704130803Smarcel      {
1705130803Smarcel	if (methcalls[i].stop_at != NULL)
1706130803Smarcel	  return find_objc_msgcall_submethod (methcalls[i].stop_at,
1707130803Smarcel					      pc, new_pc);
1708130803Smarcel	else
1709130803Smarcel	  return 0;
1710130803Smarcel      }
1711130803Smarcel
1712130803Smarcel  return 0;
1713130803Smarcel}
1714130803Smarcel
1715130803Smarcelextern initialize_file_ftype _initialize_objc_language; /* -Wmissing-prototypes */
1716130803Smarcel
1717130803Smarcelvoid
1718130803Smarcel_initialize_objc_language (void)
1719130803Smarcel{
1720130803Smarcel  add_language (&objc_language_defn);
1721130803Smarcel  add_info ("selectors", selectors_info,    /* INFO SELECTORS command.  */
1722130803Smarcel	    "All Objective-C selectors, or those matching REGEXP.");
1723130803Smarcel  add_info ("classes", classes_info, 	    /* INFO CLASSES   command.  */
1724130803Smarcel	    "All Objective-C classes, or those matching REGEXP.");
1725130803Smarcel  add_com ("print-object", class_vars, print_object_command,
1726130803Smarcel	   "Ask an Objective-C object to print itself.");
1727130803Smarcel  add_com_alias ("po", "print-object", class_vars, 1);
1728130803Smarcel}
1729130803Smarcel
1730130803Smarcelstatic void
1731130803Smarcelread_objc_method (CORE_ADDR addr, struct objc_method *method)
1732130803Smarcel{
1733130803Smarcel  method->name  = read_memory_unsigned_integer (addr + 0, 4);
1734130803Smarcel  method->types = read_memory_unsigned_integer (addr + 4, 4);
1735130803Smarcel  method->imp   = read_memory_unsigned_integer (addr + 8, 4);
1736130803Smarcel}
1737130803Smarcel
1738130803Smarcelstatic
1739130803Smarcelunsigned long read_objc_methlist_nmethods (CORE_ADDR addr)
1740130803Smarcel{
1741130803Smarcel  return read_memory_unsigned_integer (addr + 4, 4);
1742130803Smarcel}
1743130803Smarcel
1744130803Smarcelstatic void
1745130803Smarcelread_objc_methlist_method (CORE_ADDR addr, unsigned long num,
1746130803Smarcel			   struct objc_method *method)
1747130803Smarcel{
1748130803Smarcel  gdb_assert (num < read_objc_methlist_nmethods (addr));
1749130803Smarcel  read_objc_method (addr + 8 + (12 * num), method);
1750130803Smarcel}
1751130803Smarcel
1752130803Smarcelstatic void
1753130803Smarcelread_objc_object (CORE_ADDR addr, struct objc_object *object)
1754130803Smarcel{
1755130803Smarcel  object->isa = read_memory_unsigned_integer (addr, 4);
1756130803Smarcel}
1757130803Smarcel
1758130803Smarcelstatic void
1759130803Smarcelread_objc_super (CORE_ADDR addr, struct objc_super *super)
1760130803Smarcel{
1761130803Smarcel  super->receiver = read_memory_unsigned_integer (addr, 4);
1762130803Smarcel  super->class = read_memory_unsigned_integer (addr + 4, 4);
1763130803Smarcel};
1764130803Smarcel
1765130803Smarcelstatic void
1766130803Smarcelread_objc_class (CORE_ADDR addr, struct objc_class *class)
1767130803Smarcel{
1768130803Smarcel  class->isa = read_memory_unsigned_integer (addr, 4);
1769130803Smarcel  class->super_class = read_memory_unsigned_integer (addr + 4, 4);
1770130803Smarcel  class->name = read_memory_unsigned_integer (addr + 8, 4);
1771130803Smarcel  class->version = read_memory_unsigned_integer (addr + 12, 4);
1772130803Smarcel  class->info = read_memory_unsigned_integer (addr + 16, 4);
1773130803Smarcel  class->instance_size = read_memory_unsigned_integer (addr + 18, 4);
1774130803Smarcel  class->ivars = read_memory_unsigned_integer (addr + 24, 4);
1775130803Smarcel  class->methods = read_memory_unsigned_integer (addr + 28, 4);
1776130803Smarcel  class->cache = read_memory_unsigned_integer (addr + 32, 4);
1777130803Smarcel  class->protocols = read_memory_unsigned_integer (addr + 36, 4);
1778130803Smarcel}
1779130803Smarcel
1780130803Smarcelstatic CORE_ADDR
1781130803Smarcelfind_implementation_from_class (CORE_ADDR class, CORE_ADDR sel)
1782130803Smarcel{
1783130803Smarcel  CORE_ADDR subclass = class;
1784130803Smarcel
1785130803Smarcel  while (subclass != 0)
1786130803Smarcel    {
1787130803Smarcel
1788130803Smarcel      struct objc_class class_str;
1789130803Smarcel      unsigned mlistnum = 0;
1790130803Smarcel
1791130803Smarcel      read_objc_class (subclass, &class_str);
1792130803Smarcel
1793130803Smarcel      for (;;)
1794130803Smarcel	{
1795130803Smarcel	  CORE_ADDR mlist;
1796130803Smarcel	  unsigned long nmethods;
1797130803Smarcel	  unsigned long i;
1798130803Smarcel
1799130803Smarcel	  mlist = read_memory_unsigned_integer (class_str.methods +
1800130803Smarcel						(4 * mlistnum), 4);
1801130803Smarcel	  if (mlist == 0)
1802130803Smarcel	    break;
1803130803Smarcel
1804130803Smarcel	  nmethods = read_objc_methlist_nmethods (mlist);
1805130803Smarcel
1806130803Smarcel	  for (i = 0; i < nmethods; i++)
1807130803Smarcel	    {
1808130803Smarcel	      struct objc_method meth_str;
1809130803Smarcel	      read_objc_methlist_method (mlist, i, &meth_str);
1810130803Smarcel
1811130803Smarcel#if 0
1812130803Smarcel	      fprintf (stderr,
1813130803Smarcel		       "checking method 0x%lx against selector 0x%lx\n",
1814130803Smarcel		       meth_str.name, sel);
1815130803Smarcel#endif
1816130803Smarcel
1817130803Smarcel	      if (meth_str.name == sel)
1818130803Smarcel		/* FIXME: hppa arch was doing a pointer dereference
1819130803Smarcel		   here. There needs to be a better way to do that.  */
1820130803Smarcel		return meth_str.imp;
1821130803Smarcel	    }
1822130803Smarcel	  mlistnum++;
1823130803Smarcel	}
1824130803Smarcel      subclass = class_str.super_class;
1825130803Smarcel    }
1826130803Smarcel
1827130803Smarcel  return 0;
1828130803Smarcel}
1829130803Smarcel
1830130803Smarcelstatic CORE_ADDR
1831130803Smarcelfind_implementation (CORE_ADDR object, CORE_ADDR sel)
1832130803Smarcel{
1833130803Smarcel  struct objc_object ostr;
1834130803Smarcel
1835130803Smarcel  if (object == 0)
1836130803Smarcel    return 0;
1837130803Smarcel  read_objc_object (object, &ostr);
1838130803Smarcel  if (ostr.isa == 0)
1839130803Smarcel    return 0;
1840130803Smarcel
1841130803Smarcel  return find_implementation_from_class (ostr.isa, sel);
1842130803Smarcel}
1843130803Smarcel
1844130803Smarcel#define OBJC_FETCH_POINTER_ARGUMENT(argi) \
1845130803Smarcel  FETCH_POINTER_ARGUMENT (get_current_frame (), argi, builtin_type_void_func_ptr)
1846130803Smarcel
1847130803Smarcelstatic int
1848130803Smarcelresolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc)
1849130803Smarcel{
1850130803Smarcel  CORE_ADDR object;
1851130803Smarcel  CORE_ADDR sel;
1852130803Smarcel  CORE_ADDR res;
1853130803Smarcel
1854130803Smarcel  object = OBJC_FETCH_POINTER_ARGUMENT (0);
1855130803Smarcel  sel = OBJC_FETCH_POINTER_ARGUMENT (1);
1856130803Smarcel
1857130803Smarcel  res = find_implementation (object, sel);
1858130803Smarcel  if (new_pc != 0)
1859130803Smarcel    *new_pc = res;
1860130803Smarcel  if (res == 0)
1861130803Smarcel    return 1;
1862130803Smarcel  return 0;
1863130803Smarcel}
1864130803Smarcel
1865130803Smarcelstatic int
1866130803Smarcelresolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
1867130803Smarcel{
1868130803Smarcel  CORE_ADDR object;
1869130803Smarcel  CORE_ADDR sel;
1870130803Smarcel  CORE_ADDR res;
1871130803Smarcel
1872130803Smarcel  object = OBJC_FETCH_POINTER_ARGUMENT (1);
1873130803Smarcel  sel = OBJC_FETCH_POINTER_ARGUMENT (2);
1874130803Smarcel
1875130803Smarcel  res = find_implementation (object, sel);
1876130803Smarcel  if (new_pc != 0)
1877130803Smarcel    *new_pc = res;
1878130803Smarcel  if (res == 0)
1879130803Smarcel    return 1;
1880130803Smarcel  return 0;
1881130803Smarcel}
1882130803Smarcel
1883130803Smarcelstatic int
1884130803Smarcelresolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc)
1885130803Smarcel{
1886130803Smarcel  struct objc_super sstr;
1887130803Smarcel
1888130803Smarcel  CORE_ADDR super;
1889130803Smarcel  CORE_ADDR sel;
1890130803Smarcel  CORE_ADDR res;
1891130803Smarcel
1892130803Smarcel  super = OBJC_FETCH_POINTER_ARGUMENT (0);
1893130803Smarcel  sel = OBJC_FETCH_POINTER_ARGUMENT (1);
1894130803Smarcel
1895130803Smarcel  read_objc_super (super, &sstr);
1896130803Smarcel  if (sstr.class == 0)
1897130803Smarcel    return 0;
1898130803Smarcel
1899130803Smarcel  res = find_implementation_from_class (sstr.class, sel);
1900130803Smarcel  if (new_pc != 0)
1901130803Smarcel    *new_pc = res;
1902130803Smarcel  if (res == 0)
1903130803Smarcel    return 1;
1904130803Smarcel  return 0;
1905130803Smarcel}
1906130803Smarcel
1907130803Smarcelstatic int
1908130803Smarcelresolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
1909130803Smarcel{
1910130803Smarcel  struct objc_super sstr;
1911130803Smarcel
1912130803Smarcel  CORE_ADDR super;
1913130803Smarcel  CORE_ADDR sel;
1914130803Smarcel  CORE_ADDR res;
1915130803Smarcel
1916130803Smarcel  super = OBJC_FETCH_POINTER_ARGUMENT (1);
1917130803Smarcel  sel = OBJC_FETCH_POINTER_ARGUMENT (2);
1918130803Smarcel
1919130803Smarcel  read_objc_super (super, &sstr);
1920130803Smarcel  if (sstr.class == 0)
1921130803Smarcel    return 0;
1922130803Smarcel
1923130803Smarcel  res = find_implementation_from_class (sstr.class, sel);
1924130803Smarcel  if (new_pc != 0)
1925130803Smarcel    *new_pc = res;
1926130803Smarcel  if (res == 0)
1927130803Smarcel    return 1;
1928130803Smarcel  return 0;
1929130803Smarcel}
1930