1d3bb418pst/* Support for printing C++ values for GDB, the GNU debugger.
2f458c59obrien   Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3ddb504emarcel   2000, 2001, 2002, 2003
4d3bb418pst   Free Software Foundation, Inc.
5d3bb418pst
6f458c59obrien   This file is part of GDB.
7d3bb418pst
8f458c59obrien   This program is free software; you can redistribute it and/or modify
9f458c59obrien   it under the terms of the GNU General Public License as published by
10f458c59obrien   the Free Software Foundation; either version 2 of the License, or
11f458c59obrien   (at your option) any later version.
12d3bb418pst
13f458c59obrien   This program is distributed in the hope that it will be useful,
14f458c59obrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
15f458c59obrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f458c59obrien   GNU General Public License for more details.
17d3bb418pst
18f458c59obrien   You should have received a copy of the GNU General Public License
19f458c59obrien   along with this program; if not, write to the Free Software
20f458c59obrien   Foundation, Inc., 59 Temple Place - Suite 330,
21f458c59obrien   Boston, MA 02111-1307, USA.  */
22d3bb418pst
23d3bb418pst#include "defs.h"
24ddb504emarcel#include "gdb_obstack.h"
25d3bb418pst#include "symtab.h"
26d3bb418pst#include "gdbtypes.h"
27d3bb418pst#include "expression.h"
28d3bb418pst#include "value.h"
29d3bb418pst#include "command.h"
30d3bb418pst#include "gdbcmd.h"
31d3bb418pst#include "demangle.h"
32d3bb418pst#include "annotate.h"
33d3bb418pst#include "gdb_string.h"
34d3bb418pst#include "c-lang.h"
355d522dfdfr#include "target.h"
36f458c59obrien#include "cp-abi.h"
37ddb504emarcel#include "valprint.h"
385d522dfdfr
39f458c59obrien/* Indication of presence of HP-compiled object files */
40f458c59obrienextern int hp_som_som_object_present;	/* defined in symtab.c */
415d522dfdfr
42d3bb418pst
43d3bb418pstint vtblprint;			/* Controls printing of vtbl's */
44d3bb418pstint objectprint;		/* Controls looking up an object's derived type
45d3bb418pst				   using what we find in its vtables.  */
46f458c59obrienint static_field_print;		/* Controls printing of static fields. */
47d3bb418pst
48d3bb418pststatic struct obstack dont_print_vb_obstack;
49d3bb418pststatic struct obstack dont_print_statmem_obstack;
50d3bb418pst
51f458c59obrienextern void _initialize_cp_valprint (void);
52d3bb418pst
53f458c59obrienstatic void cp_print_static_field (struct type *, struct value *,
54f458c59obrien				   struct ui_file *, int, int,
55f458c59obrien				   enum val_prettyprint);
56d3bb418pst
57f458c59obrienstatic void cp_print_value (struct type *, struct type *, char *, int,
58f458c59obrien			    CORE_ADDR, struct ui_file *, int, int,
59f458c59obrien			    enum val_prettyprint, struct type **);
60f458c59obrien
61f458c59obrienstatic void cp_print_hpacc_virtual_table_entries (struct type *, int *,
62f458c59obrien						  struct value *,
63f458c59obrien						  struct ui_file *, int,
64f458c59obrien						  int,
65f458c59obrien						  enum val_prettyprint);
665d522dfdfr
675d522dfdfr
68d3bb418pstvoid
69f458c59obriencp_print_class_method (char *valaddr,
70f458c59obrien		       struct type *type,
71f458c59obrien		       struct ui_file *stream)
72d3bb418pst{
73d3bb418pst  struct type *domain;
74d3bb418pst  struct fn_field *f = NULL;
75d3bb418pst  int j = 0;
76d3bb418pst  int len2;
77d3bb418pst  int offset;
78d3bb418pst  char *kind = "";
79d3bb418pst  CORE_ADDR addr;
80d3bb418pst  struct symbol *sym;
81d3bb418pst  unsigned len;
82d3bb418pst  unsigned int i;
83d3bb418pst  struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
84d3bb418pst
85d3bb418pst  domain = TYPE_DOMAIN_TYPE (target_type);
86f458c59obrien  if (domain == (struct type *) NULL)
87d3bb418pst    {
88d3bb418pst      fprintf_filtered (stream, "<unknown>");
89d3bb418pst      return;
90d3bb418pst    }
91ddb504emarcel  addr = unpack_pointer (type, valaddr);
92d3bb418pst  if (METHOD_PTR_IS_VIRTUAL (addr))
93d3bb418pst    {
94d3bb418pst      offset = METHOD_PTR_TO_VOFFSET (addr);
95d3bb418pst      len = TYPE_NFN_FIELDS (domain);
96d3bb418pst      for (i = 0; i < len; i++)
97d3bb418pst	{
98d3bb418pst	  f = TYPE_FN_FIELDLIST1 (domain, i);
99d3bb418pst	  len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
100f458c59obrien
101ddb504emarcel	  check_stub_method_group (domain, i);
102d3bb418pst	  for (j = 0; j < len2; j++)
103d3bb418pst	    {
104d3bb418pst	      if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
105d3bb418pst		{
106d3bb418pst		  kind = "virtual ";
107d3bb418pst		  goto common;
108d3bb418pst		}
109d3bb418pst	    }
110d3bb418pst	}
111d3bb418pst    }
112d3bb418pst  else
113d3bb418pst    {
114d3bb418pst      sym = find_pc_function (addr);
115d3bb418pst      if (sym == 0)
116d3bb418pst	{
117f458c59obrien	  /* 1997-08-01 Currently unsupported with HP aCC */
118f458c59obrien	  if (hp_som_som_object_present)
119f458c59obrien	    {
120f458c59obrien	      fputs_filtered ("?? <not supported with HP aCC>", stream);
121f458c59obrien	      return;
122f458c59obrien	    }
123d3bb418pst	  error ("invalid pointer to member function");
124d3bb418pst	}
125d3bb418pst      len = TYPE_NFN_FIELDS (domain);
126d3bb418pst      for (i = 0; i < len; i++)
127d3bb418pst	{
128d3bb418pst	  f = TYPE_FN_FIELDLIST1 (domain, i);
129d3bb418pst	  len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
130f458c59obrien
131ddb504emarcel	  check_stub_method_group (domain, i);
132d3bb418pst	  for (j = 0; j < len2; j++)
133d3bb418pst	    {
134ddb504emarcel	      if (strcmp (DEPRECATED_SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))
135ddb504emarcel		  == 0)
136ddb504emarcel		goto common;
137d3bb418pst	    }
138d3bb418pst	}
139d3bb418pst    }
140f458c59obrien common:
141d3bb418pst  if (i < len)
142d3bb418pst    {
1435d522dfdfr      char *demangled_name;
1445d522dfdfr
145d3bb418pst      fprintf_filtered (stream, "&");
146ddb504emarcel      fputs_filtered (kind, stream);
1475d522dfdfr      demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
1485d522dfdfr				       DMGL_ANSI | DMGL_PARAMS);
1495d522dfdfr      if (demangled_name == NULL)
1505d522dfdfr	fprintf_filtered (stream, "<badly mangled name %s>",
1515d522dfdfr			  TYPE_FN_FIELD_PHYSNAME (f, j));
152d3bb418pst      else
153d3bb418pst	{
1545d522dfdfr	  fputs_filtered (demangled_name, stream);
155f458c59obrien	  xfree (demangled_name);
156d3bb418pst	}
157d3bb418pst    }
158d3bb418pst  else
159d3bb418pst    {
160d3bb418pst      fprintf_filtered (stream, "(");
161d3bb418pst      type_print (type, "", stream, -1);
162d3bb418pst      fprintf_filtered (stream, ") %d", (int) addr >> 3);
163d3bb418pst    }
164d3bb418pst}
165d3bb418pst
166ddb504emarcel/* GCC versions after 2.4.5 use this.  */
167f458c59obrienconst char vtbl_ptr_name[] = "__vtbl_ptr_type";
168d3bb418pst
169ddb504emarcel/* HP aCC uses different names.  */
170f458c59obrienconst char hpacc_vtbl_ptr_name[] = "__vfp";
171f458c59obrienconst char hpacc_vtbl_ptr_type_name[] = "__vftyp";
1725d522dfdfr
173d3bb418pst/* Return truth value for assertion that TYPE is of the type
174d3bb418pst   "pointer to virtual function".  */
175d3bb418pst
176d3bb418pstint
177f458c59obriencp_is_vtbl_ptr_type (struct type *type)
178d3bb418pst{
179d3bb418pst  char *typename = type_name_no_tag (type);
180d3bb418pst
181ddb504emarcel  return (typename != NULL && !strcmp (typename, vtbl_ptr_name));
182d3bb418pst}
183d3bb418pst
184d3bb418pst/* Return truth value for the assertion that TYPE is of the type
185d3bb418pst   "pointer to virtual function table".  */
186d3bb418pst
187d3bb418pstint
188f458c59obriencp_is_vtbl_member (struct type *type)
189d3bb418pst{
190ddb504emarcel  /* With older versions of g++, the vtbl field pointed to an array
191ddb504emarcel     of structures.  Nowadays it points directly to the structure. */
192d3bb418pst  if (TYPE_CODE (type) == TYPE_CODE_PTR)
193d3bb418pst    {
194d3bb418pst      type = TYPE_TARGET_TYPE (type);
195d3bb418pst      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
196d3bb418pst	{
197d3bb418pst	  type = TYPE_TARGET_TYPE (type);
198f458c59obrien	  if (TYPE_CODE (type) == TYPE_CODE_STRUCT	/* if not using thunks */
199f458c59obrien	      || TYPE_CODE (type) == TYPE_CODE_PTR)	/* if using thunks */
200d3bb418pst	    {
201d3bb418pst	      /* Virtual functions tables are full of pointers
202f458c59obrien	         to virtual functions. */
203d3bb418pst	      return cp_is_vtbl_ptr_type (type);
204d3bb418pst	    }
205d3bb418pst	}
206ddb504emarcel      else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)  /* if not using thunks */
207ddb504emarcel	{
208ddb504emarcel	  return cp_is_vtbl_ptr_type (type);
209ddb504emarcel	}
210ddb504emarcel      else if (TYPE_CODE (type) == TYPE_CODE_PTR)     /* if using thunks */
211ddb504emarcel	{
212ddb504emarcel	  /* The type name of the thunk pointer is NULL when using dwarf2.
213ddb504emarcel	     We could test for a pointer to a function, but there is
214ddb504emarcel	     no type info for the virtual table either, so it wont help.  */
215ddb504emarcel	  return cp_is_vtbl_ptr_type (type);
216ddb504emarcel	}
217d3bb418pst    }
218d3bb418pst  return 0;
219d3bb418pst}
220d3bb418pst
221d3bb418pst/* Mutually recursive subroutines of cp_print_value and c_val_print to
222d3bb418pst   print out a structure's fields: cp_print_value_fields and cp_print_value.
223f458c59obrien
224d3bb418pst   TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and PRETTY have the
225d3bb418pst   same meanings as in cp_print_value and c_val_print.
226d3bb418pst
2275d522dfdfr   2nd argument REAL_TYPE is used to carry over the type of the derived
2285d522dfdfr   class across the recursion to base classes.
2295d522dfdfr
230d3bb418pst   DONT_PRINT is an array of baseclass types that we
231d3bb418pst   should not print, or zero if called from top level.  */
232d3bb418pst
233d3bb418pstvoid
234f458c59obriencp_print_value_fields (struct type *type, struct type *real_type, char *valaddr,
235f458c59obrien		       int offset, CORE_ADDR address, struct ui_file *stream,
236f458c59obrien		       int format, int recurse, enum val_prettyprint pretty,
237f458c59obrien		       struct type **dont_print_vb, int dont_print_statmem)
238d3bb418pst{
239d3bb418pst  int i, len, n_baseclasses;
240d3bb418pst  struct obstack tmp_obstack;
241d3bb418pst  char *last_dont_print = obstack_next_free (&dont_print_statmem_obstack);
2425d522dfdfr  int fields_seen = 0;
243d3bb418pst
244d3bb418pst  CHECK_TYPEDEF (type);
245d3bb418pst
246d3bb418pst  fprintf_filtered (stream, "{");
247d3bb418pst  len = TYPE_NFIELDS (type);
248d3bb418pst  n_baseclasses = TYPE_N_BASECLASSES (type);
249d3bb418pst
2505d522dfdfr  /* First, print out baseclasses such that we don't print
251d3bb418pst     duplicates of virtual baseclasses.  */
2525d522dfdfr
253d3bb418pst  if (n_baseclasses > 0)
2545d522dfdfr    cp_print_value (type, real_type, valaddr, offset, address, stream,
255f458c59obrien		    format, recurse + 1, pretty, dont_print_vb);
256d3bb418pst
2575d522dfdfr  /* Second, print out data fields */
2585d522dfdfr
2595d522dfdfr  /* If there are no data fields, or if the only field is the
260f458c59obrien   * vtbl pointer, skip this part */
261f458c59obrien  if ((len == n_baseclasses)
262f458c59obrien      || ((len - n_baseclasses == 1)
263f458c59obrien	  && TYPE_HAS_VTABLE (type)
264ddb504emarcel	  && strncmp (TYPE_FIELD_NAME (type, n_baseclasses),
265ddb504emarcel		      hpacc_vtbl_ptr_name, 5) == 0)
266f458c59obrien      || !len)
267d3bb418pst    fprintf_filtered (stream, "<No data fields>");
268d3bb418pst  else
269d3bb418pst    {
270d3bb418pst      if (dont_print_statmem == 0)
271d3bb418pst	{
272d3bb418pst	  /* If we're at top level, carve out a completely fresh
273d3bb418pst	     chunk of the obstack and use that until this particular
274d3bb418pst	     invocation returns.  */
275d3bb418pst	  tmp_obstack = dont_print_statmem_obstack;
276d3bb418pst	  obstack_finish (&dont_print_statmem_obstack);
277d3bb418pst	}
278d3bb418pst
279d3bb418pst      for (i = n_baseclasses; i < len; i++)
280d3bb418pst	{
281d3bb418pst	  /* If requested, skip printing of static fields.  */
282d3bb418pst	  if (!static_field_print && TYPE_FIELD_STATIC (type, i))
283d3bb418pst	    continue;
2845d522dfdfr
285f458c59obrien	  /* If a vtable pointer appears, we'll print it out later */
286f458c59obrien	  if (TYPE_HAS_VTABLE (type)
287ddb504emarcel	      && strncmp (TYPE_FIELD_NAME (type, i), hpacc_vtbl_ptr_name,
288ddb504emarcel			  5) == 0)
289f458c59obrien	    continue;
290f458c59obrien
291d3bb418pst	  if (fields_seen)
292d3bb418pst	    fprintf_filtered (stream, ", ");
293d3bb418pst	  else if (n_baseclasses > 0)
294d3bb418pst	    {
295d3bb418pst	      if (pretty)
296d3bb418pst		{
297d3bb418pst		  fprintf_filtered (stream, "\n");
298d3bb418pst		  print_spaces_filtered (2 + 2 * recurse, stream);
299d3bb418pst		  fputs_filtered ("members of ", stream);
300d3bb418pst		  fputs_filtered (type_name_no_tag (type), stream);
301d3bb418pst		  fputs_filtered (": ", stream);
302d3bb418pst		}
303d3bb418pst	    }
304d3bb418pst	  fields_seen = 1;
305d3bb418pst
306d3bb418pst	  if (pretty)
307d3bb418pst	    {
308d3bb418pst	      fprintf_filtered (stream, "\n");
309d3bb418pst	      print_spaces_filtered (2 + 2 * recurse, stream);
310d3bb418pst	    }
311f458c59obrien	  else
312d3bb418pst	    {
313d3bb418pst	      wrap_here (n_spaces (2 + 2 * recurse));
314d3bb418pst	    }
315d3bb418pst	  if (inspect_it)
316d3bb418pst	    {
317d3bb418pst	      if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
318d3bb418pst		fputs_filtered ("\"( ptr \"", stream);
319d3bb418pst	      else
320d3bb418pst		fputs_filtered ("\"( nodef \"", stream);
321d3bb418pst	      if (TYPE_FIELD_STATIC (type, i))
322d3bb418pst		fputs_filtered ("static ", stream);
323d3bb418pst	      fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
324d3bb418pst				       language_cplus,
325d3bb418pst				       DMGL_PARAMS | DMGL_ANSI);
326d3bb418pst	      fputs_filtered ("\" \"", stream);
327d3bb418pst	      fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
328d3bb418pst				       language_cplus,
329d3bb418pst				       DMGL_PARAMS | DMGL_ANSI);
330d3bb418pst	      fputs_filtered ("\") \"", stream);
331d3bb418pst	    }
332d3bb418pst	  else
333d3bb418pst	    {
334d3bb418pst	      annotate_field_begin (TYPE_FIELD_TYPE (type, i));
335d3bb418pst
336d3bb418pst	      if (TYPE_FIELD_STATIC (type, i))
337d3bb418pst		fputs_filtered ("static ", stream);
338d3bb418pst	      fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
339d3bb418pst				       language_cplus,
340d3bb418pst				       DMGL_PARAMS | DMGL_ANSI);
341d3bb418pst	      annotate_field_name_end ();
3425d522dfdfr	      /* do not print leading '=' in case of anonymous unions */
3435d522dfdfr	      if (strcmp (TYPE_FIELD_NAME (type, i), ""))
3445d522dfdfr		fputs_filtered (" = ", stream);
345d3bb418pst	      annotate_field_value ();
346d3bb418pst	    }
347d3bb418pst
348d3bb418pst	  if (!TYPE_FIELD_STATIC (type, i) && TYPE_FIELD_PACKED (type, i))
349d3bb418pst	    {
350f458c59obrien	      struct value *v;
351d3bb418pst
352d3bb418pst	      /* Bitfields require special handling, especially due to byte
353f458c59obrien	         order problems.  */
354d3bb418pst	      if (TYPE_FIELD_IGNORE (type, i))
355d3bb418pst		{
356f458c59obrien		  fputs_filtered ("<optimized out or zero length>", stream);
357d3bb418pst		}
358d3bb418pst	      else
359d3bb418pst		{
360f458c59obrien		  v = value_from_longest
361f458c59obrien		    (TYPE_FIELD_TYPE (type, i),
362f458c59obrien		     unpack_field_as_long (type, valaddr + offset, i));
363d3bb418pst
36445eda7demaste		  common_val_print (v, stream, format, 0, recurse + 1, pretty);
365d3bb418pst		}
366d3bb418pst	    }
367d3bb418pst	  else
368d3bb418pst	    {
369d3bb418pst	      if (TYPE_FIELD_IGNORE (type, i))
370d3bb418pst		{
371f458c59obrien		  fputs_filtered ("<optimized out or zero length>", stream);
372d3bb418pst		}
373d3bb418pst	      else if (TYPE_FIELD_STATIC (type, i))
374d3bb418pst		{
375f458c59obrien		  struct value *v = value_static_field (type, i);
3765d522dfdfr		  if (v == NULL)
377d3bb418pst		    fputs_filtered ("<optimized out>", stream);
378d3bb418pst		  else
3795d522dfdfr		    cp_print_static_field (TYPE_FIELD_TYPE (type, i), v,
3805d522dfdfr					   stream, format, recurse + 1,
3815d522dfdfr					   pretty);
382d3bb418pst		}
383d3bb418pst	      else
384d3bb418pst		{
385f458c59obrien		  val_print (TYPE_FIELD_TYPE (type, i),
386f458c59obrien			     valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8,
387f458c59obrien			     address + TYPE_FIELD_BITPOS (type, i) / 8,
388f458c59obrien			     stream, format, 0, recurse + 1, pretty);
389d3bb418pst		}
390d3bb418pst	    }
391d3bb418pst	  annotate_field_end ();
392d3bb418pst	}
393d3bb418pst
394d3bb418pst      if (dont_print_statmem == 0)
395d3bb418pst	{
396d3bb418pst	  /* Free the space used to deal with the printing
397d3bb418pst	     of the members from top level.  */
398d3bb418pst	  obstack_free (&dont_print_statmem_obstack, last_dont_print);
399d3bb418pst	  dont_print_statmem_obstack = tmp_obstack;
400d3bb418pst	}
401d3bb418pst
402d3bb418pst      if (pretty)
403d3bb418pst	{
404d3bb418pst	  fprintf_filtered (stream, "\n");
405d3bb418pst	  print_spaces_filtered (2 * recurse, stream);
406d3bb418pst	}
407f458c59obrien    }				/* if there are data fields */
408f458c59obrien  /* Now print out the virtual table pointer if there is one */
409f458c59obrien  if (TYPE_HAS_VTABLE (type)
410ddb504emarcel      && strncmp (TYPE_FIELD_NAME (type, n_baseclasses),
411ddb504emarcel		  hpacc_vtbl_ptr_name, 5) == 0)
4125d522dfdfr    {
413f458c59obrien      struct value *v;
414f458c59obrien      /* First get the virtual table pointer and print it out */
4155d522dfdfr
4165d522dfdfr#if 0
4175d522dfdfr      fputs_filtered ("__vfp = ", stream);
4185d522dfdfr#endif
4195d522dfdfr
4205d522dfdfr      fputs_filtered (", Virtual table at ", stream);
4215d522dfdfr
4225d522dfdfr      /* pai: FIXME 32x64 problem? */
4235d522dfdfr      /* Not sure what the best notation is in the case where there is no
4245d522dfdfr         baseclass name.  */
425f458c59obrien      v = value_from_pointer (lookup_pointer_type (builtin_type_unsigned_long),
426f458c59obrien			      *(unsigned long *) (valaddr + offset));
4275d522dfdfr
42845eda7demaste      common_val_print (v, stream, format, 0, recurse + 1, pretty);
4295d522dfdfr      fields_seen = 1;
4305d522dfdfr
4315d522dfdfr      if (vtblprint)
432f458c59obrien	{
433f458c59obrien	  /* Print out function pointers in vtable. */
4345d522dfdfr
435f458c59obrien	  /* FIXME: then-clause is for non-RRBC layout of virtual
436f458c59obrien	   * table.  The RRBC case in the else-clause is yet to be
437f458c59obrien	   * implemented.  The if (1) below should be changed to a
438f458c59obrien	   * test for whether the executable we have was compiled
439f458c59obrien	   * with a version of HP aCC that doesn't have RRBC
440f458c59obrien	   * support. */
4415d522dfdfr
442f458c59obrien	  if (1)
443f458c59obrien	    {
444f458c59obrien	      /* no RRBC support; function pointers embedded directly
445f458c59obrien                 in vtable */
4465d522dfdfr
447f458c59obrien	      int vfuncs = count_virtual_fns (real_type);
4485d522dfdfr
449f458c59obrien	      fputs_filtered (" {", stream);
4505d522dfdfr
451f458c59obrien	      /* FIXME : doesn't work at present */
4525d522dfdfr#if 0
453f458c59obrien	      fprintf_filtered (stream, "%d entr%s: ", vfuncs,
454f458c59obrien				vfuncs == 1 ? "y" : "ies");
4555d522dfdfr#else
456f458c59obrien	      fputs_filtered ("not implemented", stream);
4575d522dfdfr
4585d522dfdfr
4595d522dfdfr#endif
4605d522dfdfr
461f458c59obrien	      /* recursive function that prints all virtual function entries */
4625d522dfdfr#if 0
463f458c59obrien	      cp_print_hpacc_virtual_table_entries (real_type, &vfuncs, v,
464f458c59obrien						    stream, format, recurse,
465f458c59obrien						    pretty);
4665d522dfdfr#endif
467f458c59obrien	      fputs_filtered ("}", stream);
468f458c59obrien	    }			/* non-RRBC case */
469f458c59obrien	  else
470f458c59obrien	    {
471f458c59obrien	      /* FIXME -- see comments above */
472f458c59obrien	      /* RRBC support present; function pointers are found
473f458c59obrien	       * by indirection through the class segment entries. */
474f458c59obrien
475f458c59obrien
476f458c59obrien	    }			/* RRBC case */
477f458c59obrien	}			/* if vtblprint */
4785d522dfdfr
4795d522dfdfr      if (pretty)
4805d522dfdfr	{
4815d522dfdfr	  fprintf_filtered (stream, "\n");
4825d522dfdfr	  print_spaces_filtered (2 * recurse, stream);
4835d522dfdfr	}
4845d522dfdfr
485f458c59obrien    }				/* if vtable exists */
486f458c59obrien
487d3bb418pst  fprintf_filtered (stream, "}");
488d3bb418pst}
489d3bb418pst
490d3bb418pst/* Special val_print routine to avoid printing multiple copies of virtual
491d3bb418pst   baseclasses.  */
492d3bb418pst
493d3bb418pststatic void
494f458c59obriencp_print_value (struct type *type, struct type *real_type, char *valaddr,
495f458c59obrien		int offset, CORE_ADDR address, struct ui_file *stream,
496f458c59obrien		int format, int recurse, enum val_prettyprint pretty,
497f458c59obrien		struct type **dont_print_vb)
498d3bb418pst{
499d3bb418pst  struct obstack tmp_obstack;
500d3bb418pst  struct type **last_dont_print
501f458c59obrien    = (struct type **) obstack_next_free (&dont_print_vb_obstack);
502d3bb418pst  int i, n_baseclasses = TYPE_N_BASECLASSES (type);
503f458c59obrien  int thisoffset;
504f458c59obrien  struct type *thistype;
505d3bb418pst
506d3bb418pst  if (dont_print_vb == 0)
507d3bb418pst    {
508d3bb418pst      /* If we're at top level, carve out a completely fresh
509f458c59obrien         chunk of the obstack and use that until this particular
510f458c59obrien         invocation returns.  */
511d3bb418pst      tmp_obstack = dont_print_vb_obstack;
512d3bb418pst      /* Bump up the high-water mark.  Now alpha is omega.  */
513d3bb418pst      obstack_finish (&dont_print_vb_obstack);
514d3bb418pst    }
515d3bb418pst
516d3bb418pst  for (i = 0; i < n_baseclasses; i++)
517d3bb418pst    {
518d3bb418pst      int boffset;
5195d522dfdfr      int skip;
520d3bb418pst      struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
521d3bb418pst      char *basename = TYPE_NAME (baseclass);
5225d522dfdfr      char *base_valaddr;
523d3bb418pst
524d3bb418pst      if (BASETYPE_VIA_VIRTUAL (type, i))
525d3bb418pst	{
526d3bb418pst	  struct type **first_dont_print
527f458c59obrien	    = (struct type **) obstack_base (&dont_print_vb_obstack);
528d3bb418pst
529f458c59obrien	  int j = (struct type **) obstack_next_free (&dont_print_vb_obstack)
530d3bb418pst	    - first_dont_print;
531d3bb418pst
532d3bb418pst	  while (--j >= 0)
533d3bb418pst	    if (baseclass == first_dont_print[j])
534d3bb418pst	      goto flush_it;
535d3bb418pst
536d3bb418pst	  obstack_ptr_grow (&dont_print_vb_obstack, baseclass);
537d3bb418pst	}
538d3bb418pst
539f458c59obrien      thisoffset = offset;
540f458c59obrien      thistype = real_type;
5415d522dfdfr      if (TYPE_HAS_VTABLE (type) && BASETYPE_VIA_VIRTUAL (type, i))
542f458c59obrien	{
543f458c59obrien	  /* Assume HP/Taligent runtime convention */
544f458c59obrien	  find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
545f458c59obrien				valaddr, offset, &boffset, &skip);
546f458c59obrien	  if (skip >= 0)
547f458c59obrien	    error ("Virtual base class offset not found from vtable while"
548f458c59obrien		   " printing");
549f458c59obrien	  base_valaddr = valaddr;
550f458c59obrien	}
5515d522dfdfr      else
552f458c59obrien	{
553f458c59obrien	  boffset = baseclass_offset (type, i,
554f458c59obrien				      valaddr + offset,
555ddb504emarcel				      address);
556f458c59obrien	  skip = ((boffset == -1) || (boffset + offset) < 0) ? 1 : -1;
557f458c59obrien
558f458c59obrien	  if (BASETYPE_VIA_VIRTUAL (type, i))
559f458c59obrien	    {
560f458c59obrien	      /* The virtual base class pointer might have been
561f458c59obrien	         clobbered by the user program. Make sure that it
562f458c59obrien	         still points to a valid memory location.  */
563f458c59obrien
564f458c59obrien	      if (boffset != -1
565f458c59obrien		  && ((boffset + offset) < 0
566f458c59obrien		      || (boffset + offset) >= TYPE_LENGTH (type)))
567f458c59obrien		{
568f458c59obrien		  /* FIXME (alloca): unsafe if baseclass is really really large. */
569f458c59obrien		  base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass));
570ddb504emarcel		  if (target_read_memory (address + boffset, base_valaddr,
571f458c59obrien					  TYPE_LENGTH (baseclass)) != 0)
572f458c59obrien		    skip = 1;
573ddb504emarcel		  address = address + boffset;
574f458c59obrien		  thisoffset = 0;
575f458c59obrien		  boffset = 0;
576f458c59obrien		  thistype = baseclass;
577f458c59obrien		}
578f458c59obrien	      else
579f458c59obrien		base_valaddr = valaddr;
580f458c59obrien	    }
581f458c59obrien	  else
582f458c59obrien	    base_valaddr = valaddr;
5835d522dfdfr	}
584d3bb418pst
5855d522dfdfr      /* now do the printing */
586d3bb418pst      if (pretty)
587d3bb418pst	{
588d3bb418pst	  fprintf_filtered (stream, "\n");
589d3bb418pst	  print_spaces_filtered (2 * recurse, stream);
590d3bb418pst	}
591d3bb418pst      fputs_filtered ("<", stream);
592d3bb418pst      /* Not sure what the best notation is in the case where there is no
593f458c59obrien         baseclass name.  */
594d3bb418pst      fputs_filtered (basename ? basename : "", stream);
595d3bb418pst      fputs_filtered ("> = ", stream);
5965d522dfdfr
5975d522dfdfr
5985d522dfdfr      if (skip >= 1)
599d3bb418pst	fprintf_filtered (stream, "<invalid address>");
600d3bb418pst      else
601f458c59obrien	cp_print_value_fields (baseclass, thistype, base_valaddr,
602ddb504emarcel			       thisoffset + boffset, address + boffset,
603ddb504emarcel			       stream, format,
604f458c59obrien			       recurse, pretty,
605f458c59obrien			       ((struct type **)
606f458c59obrien				obstack_base (&dont_print_vb_obstack)),
607d3bb418pst			       0);
608d3bb418pst      fputs_filtered (", ", stream);
609d3bb418pst
610d3bb418pst    flush_it:
611d3bb418pst      ;
612d3bb418pst    }
613d3bb418pst
614d3bb418pst  if (dont_print_vb == 0)
615d3bb418pst    {
616d3bb418pst      /* Free the space used to deal with the printing
617f458c59obrien         of this type from top level.  */
618d3bb418pst      obstack_free (&dont_print_vb_obstack, last_dont_print);
619d3bb418pst      /* Reset watermark so that we can continue protecting
620f458c59obrien         ourselves from whatever we were protecting ourselves.  */
621d3bb418pst      dont_print_vb_obstack = tmp_obstack;
622d3bb418pst    }
623d3bb418pst}
624d3bb418pst
625d3bb418pst/* Print value of a static member.
626d3bb418pst   To avoid infinite recursion when printing a class that contains
627d3bb418pst   a static instance of the class, we keep the addresses of all printed
628d3bb418pst   static member classes in an obstack and refuse to print them more
629d3bb418pst   than once.
630d3bb418pst
631d3bb418pst   VAL contains the value to print, TYPE, STREAM, RECURSE, and PRETTY
632d3bb418pst   have the same meanings as in c_val_print.  */
633d3bb418pst
634d3bb418pststatic void
635f458c59obriencp_print_static_field (struct type *type,
636f458c59obrien		       struct value *val,
637f458c59obrien		       struct ui_file *stream,
638f458c59obrien		       int format,
639f458c59obrien		       int recurse,
640f458c59obrien		       enum val_prettyprint pretty)
641d3bb418pst{
642d3bb418pst  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
643d3bb418pst    {
644d3bb418pst      CORE_ADDR *first_dont_print;
645d3bb418pst      int i;
646d3bb418pst
647d3bb418pst      first_dont_print
648f458c59obrien	= (CORE_ADDR *) obstack_base (&dont_print_statmem_obstack);
649f458c59obrien      i = (CORE_ADDR *) obstack_next_free (&dont_print_statmem_obstack)
650d3bb418pst	- first_dont_print;
651d3bb418pst
652d3bb418pst      while (--i >= 0)
653d3bb418pst	{
654d3bb418pst	  if (VALUE_ADDRESS (val) == first_dont_print[i])
655d3bb418pst	    {
656f458c59obrien	      fputs_filtered ("<same as static member of an already"
657f458c59obrien			      " seen type>",
658d3bb418pst			      stream);
659d3bb418pst	      return;
660d3bb418pst	    }
661d3bb418pst	}
662d3bb418pst
663d3bb418pst      obstack_grow (&dont_print_statmem_obstack, (char *) &VALUE_ADDRESS (val),
664d3bb418pst		    sizeof (CORE_ADDR));
665d3bb418pst
666d3bb418pst      CHECK_TYPEDEF (type);
667f458c59obrien      cp_print_value_fields (type, type, VALUE_CONTENTS_ALL (val),
668f458c59obrien			     VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
669d3bb418pst			     stream, format, recurse, pretty, NULL, 1);
670d3bb418pst      return;
671d3bb418pst    }
672f458c59obrien  val_print (type, VALUE_CONTENTS_ALL (val),
673f458c59obrien	     VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
674d3bb418pst	     stream, format, 0, recurse, pretty);
675d3bb418pst}
676d3bb418pst
677d3bb418pstvoid
678f458c59obriencp_print_class_member (char *valaddr, struct type *domain,
679f458c59obrien		       struct ui_file *stream, char *prefix)
680d3bb418pst{
681f458c59obrien
682d3bb418pst  /* VAL is a byte offset into the structure type DOMAIN.
683d3bb418pst     Find the name of the field for that offset and
684d3bb418pst     print it.  */
685d3bb418pst  int extra = 0;
686d3bb418pst  int bits = 0;
687ddb504emarcel  unsigned int i;
688d3bb418pst  unsigned len = TYPE_NFIELDS (domain);
6895d522dfdfr
690d3bb418pst  /* @@ Make VAL into bit offset */
6915d522dfdfr
6925d522dfdfr  /* Note: HP aCC generates offsets that are the real byte offsets added
6935d522dfdfr     to a constant bias 0x20000000 (1 << 29).  This constant bias gets
6945d522dfdfr     shifted out in the code below -- joyous happenstance! */
6955d522dfdfr
6965d522dfdfr  /* Note: HP cfront uses a constant bias of 1; if we support this
697f458c59obrien     compiler ever, we will have to adjust the computation below */
698f458c59obrien
699d3bb418pst  LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
700d3bb418pst  for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
701d3bb418pst    {
702d3bb418pst      int bitpos = TYPE_FIELD_BITPOS (domain, i);
703d3bb418pst      QUIT;
704d3bb418pst      if (val == bitpos)
705d3bb418pst	break;
706d3bb418pst      if (val < bitpos && i != 0)
707d3bb418pst	{
708d3bb418pst	  /* Somehow pointing into a field.  */
709d3bb418pst	  i -= 1;
710d3bb418pst	  extra = (val - TYPE_FIELD_BITPOS (domain, i));
711d3bb418pst	  if (extra & 0x7)
712d3bb418pst	    bits = 1;
713d3bb418pst	  else
714d3bb418pst	    extra >>= 3;
715d3bb418pst	  break;
716d3bb418pst	}
717d3bb418pst    }
718d3bb418pst  if (i < len)
719d3bb418pst    {
720d3bb418pst      char *name;
721ddb504emarcel      fputs_filtered (prefix, stream);
722d3bb418pst      name = type_name_no_tag (domain);
723d3bb418pst      if (name)
724f458c59obrien	fputs_filtered (name, stream);
725d3bb418pst      else
726d3bb418pst	c_type_print_base (domain, stream, 0, 0);
727d3bb418pst      fprintf_filtered (stream, "::");
728d3bb418pst      fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
729d3bb418pst      if (extra)
730d3bb418pst	fprintf_filtered (stream, " + %d bytes", extra);
731d3bb418pst      if (bits)
732d3bb418pst	fprintf_filtered (stream, " (offset in bits)");
733d3bb418pst    }
734d3bb418pst  else
735f458c59obrien    fprintf_filtered (stream, "%ld", (long) (val >> 3));
736d3bb418pst}
737d3bb418pst
7385d522dfdfr
7395d522dfdfr/* This function prints out virtual table entries for a class; it
7405d522dfdfr * recurses on the base classes to find all virtual functions
7415d522dfdfr * available in a class.
7425d522dfdfr *
7435d522dfdfr * pai/1997-05-21 Note: As the name suggests, it's currently
7445d522dfdfr * implemented for HP aCC runtime only. g++ objects are handled
7455d522dfdfr * differently and I have made no attempt to fold that logic in
7465d522dfdfr * here. The runtime layout is different for the two cases.  Also,
7475d522dfdfr * this currently has only the code for non-RRBC layouts generated by
7485d522dfdfr * the HP aCC compiler; RRBC code is stubbed out and will have to be
7495d522dfdfr * added later. */
750f458c59obrien
7515d522dfdfr
7525d522dfdfrstatic void
753f458c59obriencp_print_hpacc_virtual_table_entries (struct type *type, int *vfuncs,
754f458c59obrien				      struct value *v, struct ui_file *stream,
755f458c59obrien				      int format, int recurse,
756f458c59obrien				      enum val_prettyprint pretty)
7575d522dfdfr{
7585d522dfdfr  int fn, oi;
7595d522dfdfr
7605d522dfdfr  /* pai: FIXME this function doesn't work. It should handle a given
7615d522dfdfr   * virtual function only once (latest redefinition in class hierarchy)
7625d522dfdfr   */
7635d522dfdfr
764f458c59obrien  /* Recursion on other classes that can share the same vtable */
765f458c59obrien  struct type *pbc = primary_base_class (type);
7665d522dfdfr  if (pbc)
767f458c59obrien    cp_print_hpacc_virtual_table_entries (pbc, vfuncs, v, stream, format,
768f458c59obrien					  recurse, pretty);
769f458c59obrien
7705d522dfdfr  /* Now deal with vfuncs declared in this class */
7715d522dfdfr  for (fn = 0; fn < TYPE_NFN_FIELDS (type); fn++)
7725d522dfdfr    for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (type, fn); oi++)
7735d522dfdfr      if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (type, fn), oi))
774f458c59obrien	{
775f458c59obrien	  char *vf_name;
776f458c59obrien	  const char *field_physname;
777f458c59obrien
778f458c59obrien	  /* virtual function offset */
779f458c59obrien	  int vx = (TYPE_FN_FIELD_VOFFSET (TYPE_FN_FIELDLIST1 (type, fn), oi)
780f458c59obrien		    - 1);
781f458c59obrien
782f458c59obrien	  /* Get the address of the vfunction entry */
783f458c59obrien	  struct value *vf = value_copy (v);
784f458c59obrien	  if (VALUE_LAZY (vf))
785f458c59obrien	    (void) value_fetch_lazy (vf);
786f458c59obrien	  /* adjust by offset */
787f458c59obrien	  vf->aligner.contents[0] += 4 * (HP_ACC_VFUNC_START + vx);
788f458c59obrien	  vf = value_ind (vf);	/* get the entry */
789f458c59obrien	  VALUE_TYPE (vf) = VALUE_TYPE (v);	/* make it a pointer */
790f458c59obrien
791f458c59obrien	  /* print out the entry */
79245eda7demaste	  common_val_print (vf, stream, format, 0, recurse + 1, pretty);
793f458c59obrien	  field_physname
794f458c59obrien	    = TYPE_FN_FIELD_PHYSNAME (TYPE_FN_FIELDLIST1 (type, fn), oi);
795f458c59obrien	  /* pai: (temp) FIXME Maybe this should be DMGL_ANSI */
796f458c59obrien	  vf_name = cplus_demangle (field_physname, DMGL_ARM);
797f458c59obrien	  fprintf_filtered (stream, " %s", vf_name);
798f458c59obrien	  if (--(*vfuncs) > 0)
799f458c59obrien	    fputs_filtered (", ", stream);
800f458c59obrien	}
8015d522dfdfr}
8025d522dfdfr
8035d522dfdfr
8045d522dfdfr
805d3bb418pstvoid
806f458c59obrien_initialize_cp_valprint (void)
807d3bb418pst{
808d3bb418pst  add_show_from_set
809d3bb418pst    (add_set_cmd ("static-members", class_support, var_boolean,
810f458c59obrien		  (char *) &static_field_print,
811d3bb418pst		  "Set printing of C++ static members.",
812d3bb418pst		  &setprintlist),
813d3bb418pst     &showprintlist);
814d3bb418pst  /* Turn on printing of static fields.  */
815d3bb418pst  static_field_print = 1;
816d3bb418pst
817d3bb418pst  add_show_from_set
818f458c59obrien    (add_set_cmd ("vtbl", class_support, var_boolean, (char *) &vtblprint,
819d3bb418pst		  "Set printing of C++ virtual function tables.",
820d3bb418pst		  &setprintlist),
821d3bb418pst     &showprintlist);
822d3bb418pst
823d3bb418pst  add_show_from_set
824f458c59obrien    (add_set_cmd ("object", class_support, var_boolean, (char *) &objectprint,
825f458c59obrien	      "Set printing of object's derived type based on vtable info.",
826d3bb418pst		  &setprintlist),
827d3bb418pst     &showprintlist);
828d3bb418pst
829d3bb418pst  /* Give people the defaults which they are used to.  */
830d3bb418pst  objectprint = 0;
831d3bb418pst  vtblprint = 0;
832d3bb418pst  obstack_begin (&dont_print_vb_obstack, 32 * sizeof (struct type *));
833d3bb418pst  obstack_specify_allocation (&dont_print_statmem_obstack,
834d3bb418pst			      32 * sizeof (CORE_ADDR), sizeof (CORE_ADDR),
835f458c59obrien			      xmalloc, xfree);
836d3bb418pst}
837