133965Sjdp/* prdbg.c -- Print out generic debugging information.
2218822Sdim   Copyright 1995, 1996, 1999, 2002, 2003, 2004, 2006, 2007
3218822Sdim   Free Software Foundation, Inc.
433965Sjdp   Written by Ian Lance Taylor <ian@cygnus.com>.
5130561Sobrien   Tags style generation written by Salvador E. Tropea <set@computer.org>.
633965Sjdp
733965Sjdp   This file is part of GNU Binutils.
833965Sjdp
933965Sjdp   This program is free software; you can redistribute it and/or modify
1033965Sjdp   it under the terms of the GNU General Public License as published by
1133965Sjdp   the Free Software Foundation; either version 2 of the License, or
1233965Sjdp   (at your option) any later version.
1333965Sjdp
1433965Sjdp   This program is distributed in the hope that it will be useful,
1533965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1633965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1733965Sjdp   GNU General Public License for more details.
1833965Sjdp
1933965Sjdp   You should have received a copy of the GNU General Public License
2033965Sjdp   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22218822Sdim   02110-1301, USA.  */
2333965Sjdp
2433965Sjdp/* This file prints out the generic debugging information, by
2533965Sjdp   supplying a set of routines to debug_write.  */
2633965Sjdp
27218822Sdim#include "sysdep.h"
2833965Sjdp#include <assert.h>
2933965Sjdp#include "bfd.h"
3033965Sjdp#include "libiberty.h"
31218822Sdim#include "demangle.h"
3233965Sjdp#include "debug.h"
3333965Sjdp#include "budbg.h"
3433965Sjdp
3533965Sjdp/* This is the structure we use as a handle for these routines.  */
3633965Sjdp
3733965Sjdpstruct pr_handle
3833965Sjdp{
3933965Sjdp  /* File to print information to.  */
4033965Sjdp  FILE *f;
4133965Sjdp  /* Current indentation level.  */
4233965Sjdp  unsigned int indent;
4333965Sjdp  /* Type stack.  */
4433965Sjdp  struct pr_stack *stack;
4533965Sjdp  /* Parameter number we are about to output.  */
4633965Sjdp  int parameter;
47130561Sobrien  /* The following are used only by the tags code (tg_).  */
48130561Sobrien  /* Name of the file we are using.  */
49130561Sobrien  char *filename;
50130561Sobrien  /* The BFD.  */
51130561Sobrien  bfd *abfd;
52130561Sobrien  /* The symbols table for this BFD.  */
53130561Sobrien  asymbol **syms;
54130561Sobrien  /* Pointer to a function to demangle symbols.  */
55218822Sdim  char *(*demangler) (bfd *, const char *, int);
5633965Sjdp};
5733965Sjdp
5833965Sjdp/* The type stack.  */
5933965Sjdp
6033965Sjdpstruct pr_stack
6133965Sjdp{
6233965Sjdp  /* Next element on the stack.  */
6333965Sjdp  struct pr_stack *next;
6433965Sjdp  /* This element.  */
6533965Sjdp  char *type;
6633965Sjdp  /* Current visibility of fields if this is a class.  */
6733965Sjdp  enum debug_visibility visibility;
6833965Sjdp  /* Name of the current method we are handling.  */
6933965Sjdp  const char *method;
70130561Sobrien  /* The following are used only by the tags code (tg_).  */
71130561Sobrien  /* Type for the container (struct, union, class, union class).  */
72130561Sobrien  const char *flavor;
73130561Sobrien  /* A comma separated list of parent classes.  */
74130561Sobrien  char *parents;
75130561Sobrien  /* How many parents contains parents.  */
76130561Sobrien  int num_parents;
7733965Sjdp};
7833965Sjdp
79130561Sobrienstatic void indent (struct pr_handle *);
80130561Sobrienstatic bfd_boolean push_type (struct pr_handle *, const char *);
81130561Sobrienstatic bfd_boolean prepend_type (struct pr_handle *, const char *);
82130561Sobrienstatic bfd_boolean append_type (struct pr_handle *, const char *);
83130561Sobrienstatic bfd_boolean substitute_type (struct pr_handle *, const char *);
84130561Sobrienstatic bfd_boolean indent_type (struct pr_handle *);
85130561Sobrienstatic char *pop_type (struct pr_handle *);
86130561Sobrienstatic void print_vma (bfd_vma, char *, bfd_boolean, bfd_boolean);
87130561Sobrienstatic bfd_boolean pr_fix_visibility
88130561Sobrien  (struct pr_handle *, enum debug_visibility);
89130561Sobrienstatic bfd_boolean pr_start_compilation_unit (void *, const char *);
90130561Sobrienstatic bfd_boolean pr_start_source (void *, const char *);
91130561Sobrienstatic bfd_boolean pr_empty_type (void *);
92130561Sobrienstatic bfd_boolean pr_void_type (void *);
93130561Sobrienstatic bfd_boolean pr_int_type (void *, unsigned int, bfd_boolean);
94130561Sobrienstatic bfd_boolean pr_float_type (void *, unsigned int);
95130561Sobrienstatic bfd_boolean pr_complex_type (void *, unsigned int);
96130561Sobrienstatic bfd_boolean pr_bool_type (void *, unsigned int);
97130561Sobrienstatic bfd_boolean pr_enum_type
98130561Sobrien  (void *, const char *, const char **, bfd_signed_vma *);
99130561Sobrienstatic bfd_boolean pr_pointer_type (void *);
100130561Sobrienstatic bfd_boolean pr_function_type (void *, int, bfd_boolean);
101130561Sobrienstatic bfd_boolean pr_reference_type (void *);
102130561Sobrienstatic bfd_boolean pr_range_type (void *, bfd_signed_vma, bfd_signed_vma);
103130561Sobrienstatic bfd_boolean pr_array_type
104130561Sobrien  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
105130561Sobrienstatic bfd_boolean pr_set_type (void *, bfd_boolean);
106130561Sobrienstatic bfd_boolean pr_offset_type (void *);
107130561Sobrienstatic bfd_boolean pr_method_type (void *, bfd_boolean, int, bfd_boolean);
108130561Sobrienstatic bfd_boolean pr_const_type (void *);
109130561Sobrienstatic bfd_boolean pr_volatile_type (void *);
110130561Sobrienstatic bfd_boolean pr_start_struct_type
111130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
112130561Sobrienstatic bfd_boolean pr_struct_field
113130561Sobrien  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
114130561Sobrienstatic bfd_boolean pr_end_struct_type (void *);
115130561Sobrienstatic bfd_boolean pr_start_class_type
116130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int,
117130561Sobrien   bfd_boolean, bfd_boolean);
118130561Sobrienstatic bfd_boolean pr_class_static_member
119130561Sobrien  (void *, const char *, const char *, enum debug_visibility);
120130561Sobrienstatic bfd_boolean pr_class_baseclass
121130561Sobrien  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
122130561Sobrienstatic bfd_boolean pr_class_start_method (void *, const char *);
123130561Sobrienstatic bfd_boolean pr_class_method_variant
124130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
125130561Sobrien   bfd_vma, bfd_boolean);
126130561Sobrienstatic bfd_boolean pr_class_static_method_variant
127130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
128130561Sobrienstatic bfd_boolean pr_class_end_method (void *);
129130561Sobrienstatic bfd_boolean pr_end_class_type (void *);
130130561Sobrienstatic bfd_boolean pr_typedef_type (void *, const char *);
131130561Sobrienstatic bfd_boolean pr_tag_type
132130561Sobrien  (void *, const char *, unsigned int, enum debug_type_kind);
133130561Sobrienstatic bfd_boolean pr_typdef (void *, const char *);
134130561Sobrienstatic bfd_boolean pr_tag (void *, const char *);
135130561Sobrienstatic bfd_boolean pr_int_constant (void *, const char *, bfd_vma);
136130561Sobrienstatic bfd_boolean pr_float_constant (void *, const char *, double);
137130561Sobrienstatic bfd_boolean pr_typed_constant (void *, const char *, bfd_vma);
138130561Sobrienstatic bfd_boolean pr_variable
139130561Sobrien  (void *, const char *, enum debug_var_kind, bfd_vma);
140130561Sobrienstatic bfd_boolean pr_start_function (void *, const char *, bfd_boolean);
141130561Sobrienstatic bfd_boolean pr_function_parameter
142130561Sobrien  (void *, const char *, enum debug_parm_kind, bfd_vma);
143130561Sobrienstatic bfd_boolean pr_start_block (void *, bfd_vma);
144130561Sobrienstatic bfd_boolean pr_end_block (void *, bfd_vma);
145130561Sobrienstatic bfd_boolean pr_end_function (void *);
146130561Sobrienstatic bfd_boolean pr_lineno (void *, const char *, unsigned long, bfd_vma);
147130561Sobrienstatic bfd_boolean append_parent (struct pr_handle *, const char *);
148130561Sobrien/* Only used by tg_ code.  */
149130561Sobrienstatic bfd_boolean tg_fix_visibility
150130561Sobrien  (struct pr_handle *, enum debug_visibility);
151130561Sobrienstatic void find_address_in_section (bfd *, asection *, void *);
152130561Sobrienstatic void translate_addresses (bfd *, char *, FILE *, asymbol **);
153130561Sobrienstatic const char *visibility_name (enum debug_visibility);
154130561Sobrien/* Tags style replacements.  */
155130561Sobrienstatic bfd_boolean tg_start_compilation_unit (void *, const char *);
156130561Sobrienstatic bfd_boolean tg_start_source (void *, const char *);
157130561Sobrienstatic bfd_boolean tg_enum_type
158130561Sobrien  (void *, const char *, const char **, bfd_signed_vma *);
159130561Sobrienstatic bfd_boolean tg_start_struct_type
160130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
161130561Sobrienstatic bfd_boolean pr_struct_field
162130561Sobrien  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
163130561Sobrienstatic bfd_boolean tg_struct_field
164130561Sobrien  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
165130561Sobrienstatic bfd_boolean tg_struct_field
166130561Sobrien  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
167130561Sobrienstatic bfd_boolean tg_end_struct_type (void *);
168130561Sobrienstatic bfd_boolean tg_start_class_type
169130561Sobrien  (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, bfd_boolean);
170130561Sobrienstatic bfd_boolean tg_class_static_member
171130561Sobrien  (void *, const char *, const char *, enum debug_visibility);
172130561Sobrienstatic bfd_boolean tg_class_baseclass
173130561Sobrien  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
174130561Sobrienstatic bfd_boolean tg_class_method_variant
175130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
176130561Sobrienstatic bfd_boolean tg_class_static_method_variant
177130561Sobrien  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
178130561Sobrienstatic bfd_boolean tg_end_class_type (void *);
179130561Sobrienstatic bfd_boolean tg_tag_type
180130561Sobrien  (void *, const char *, unsigned int, enum debug_type_kind);
181130561Sobrienstatic bfd_boolean tg_typdef (void *, const char *);
182130561Sobrienstatic bfd_boolean tg_tag (void *, const char *);
183130561Sobrienstatic bfd_boolean tg_int_constant (void *, const char *, bfd_vma);
184130561Sobrienstatic bfd_boolean tg_float_constant (void *, const char *, double);
185130561Sobrienstatic bfd_boolean tg_typed_constant (void *, const char *, bfd_vma);
186130561Sobrienstatic bfd_boolean tg_variable
187130561Sobrien  (void *, const char *, enum debug_var_kind, bfd_vma);
188130561Sobrienstatic bfd_boolean tg_start_function (void *, const char *, bfd_boolean);
189130561Sobrienstatic bfd_boolean tg_function_parameter
190130561Sobrien  (void *, const char *, enum debug_parm_kind, bfd_vma);
191130561Sobrienstatic bfd_boolean tg_start_block (void *, bfd_vma);
192130561Sobrienstatic bfd_boolean tg_end_block (void *, bfd_vma);
193130561Sobrienstatic bfd_boolean tg_lineno (void *, const char *, unsigned long, bfd_vma);
194130561Sobrien
19533965Sjdpstatic const struct debug_write_fns pr_fns =
19633965Sjdp{
19733965Sjdp  pr_start_compilation_unit,
19833965Sjdp  pr_start_source,
19933965Sjdp  pr_empty_type,
20033965Sjdp  pr_void_type,
20133965Sjdp  pr_int_type,
20233965Sjdp  pr_float_type,
20333965Sjdp  pr_complex_type,
20433965Sjdp  pr_bool_type,
20533965Sjdp  pr_enum_type,
20633965Sjdp  pr_pointer_type,
20733965Sjdp  pr_function_type,
20833965Sjdp  pr_reference_type,
20933965Sjdp  pr_range_type,
21033965Sjdp  pr_array_type,
21133965Sjdp  pr_set_type,
21233965Sjdp  pr_offset_type,
21333965Sjdp  pr_method_type,
21433965Sjdp  pr_const_type,
21533965Sjdp  pr_volatile_type,
21633965Sjdp  pr_start_struct_type,
21733965Sjdp  pr_struct_field,
21833965Sjdp  pr_end_struct_type,
21933965Sjdp  pr_start_class_type,
22033965Sjdp  pr_class_static_member,
22133965Sjdp  pr_class_baseclass,
22233965Sjdp  pr_class_start_method,
22333965Sjdp  pr_class_method_variant,
22433965Sjdp  pr_class_static_method_variant,
22533965Sjdp  pr_class_end_method,
22633965Sjdp  pr_end_class_type,
22733965Sjdp  pr_typedef_type,
22833965Sjdp  pr_tag_type,
22933965Sjdp  pr_typdef,
23033965Sjdp  pr_tag,
23133965Sjdp  pr_int_constant,
23233965Sjdp  pr_float_constant,
23333965Sjdp  pr_typed_constant,
23433965Sjdp  pr_variable,
23533965Sjdp  pr_start_function,
23633965Sjdp  pr_function_parameter,
23733965Sjdp  pr_start_block,
23833965Sjdp  pr_end_block,
23933965Sjdp  pr_end_function,
24033965Sjdp  pr_lineno
24133965Sjdp};
24233965Sjdp
243130561Sobrienstatic const struct debug_write_fns tg_fns =
244130561Sobrien{
245130561Sobrien  tg_start_compilation_unit,
246130561Sobrien  tg_start_source,
247130561Sobrien  pr_empty_type,		/* Same, push_type.  */
248130561Sobrien  pr_void_type,			/* Same, push_type.  */
249130561Sobrien  pr_int_type,			/* Same, push_type.  */
250130561Sobrien  pr_float_type,		/* Same, push_type.  */
251130561Sobrien  pr_complex_type,		/* Same, push_type.  */
252130561Sobrien  pr_bool_type,			/* Same, push_type.  */
253130561Sobrien  tg_enum_type,
254130561Sobrien  pr_pointer_type,		/* Same, changes to pointer.  */
255130561Sobrien  pr_function_type,		/* Same, push_type.  */
256130561Sobrien  pr_reference_type,		/* Same, changes to reference.  */
257130561Sobrien  pr_range_type,		/* FIXME: What's that?.  */
258130561Sobrien  pr_array_type,		/* Same, push_type.  */
259130561Sobrien  pr_set_type,			/* FIXME: What's that?.  */
260130561Sobrien  pr_offset_type,		/* FIXME: What's that?.  */
261130561Sobrien  pr_method_type,		/* Same.  */
262130561Sobrien  pr_const_type,		/* Same, changes to const.  */
263130561Sobrien  pr_volatile_type,		/* Same, changes to volatile.  */
264130561Sobrien  tg_start_struct_type,
265130561Sobrien  tg_struct_field,
266130561Sobrien  tg_end_struct_type,
267130561Sobrien  tg_start_class_type,
268130561Sobrien  tg_class_static_member,
269130561Sobrien  tg_class_baseclass,
270130561Sobrien  pr_class_start_method,	/* Same, remembers that's a method.  */
271130561Sobrien  tg_class_method_variant,
272130561Sobrien  tg_class_static_method_variant,
273130561Sobrien  pr_class_end_method,		/* Same, forgets that's a method.  */
274130561Sobrien  tg_end_class_type,
275130561Sobrien  pr_typedef_type,		/* Same, just push type.  */
276130561Sobrien  tg_tag_type,
277130561Sobrien  tg_typdef,
278130561Sobrien  tg_tag,
279130561Sobrien  tg_int_constant,		/* Untested.  */
280130561Sobrien  tg_float_constant,		/* Untested.  */
281130561Sobrien  tg_typed_constant,		/* Untested.  */
282130561Sobrien  tg_variable,
283130561Sobrien  tg_start_function,
284130561Sobrien  tg_function_parameter,
285130561Sobrien  tg_start_block,
286130561Sobrien  tg_end_block,
287130561Sobrien  pr_end_function,		/* Same, does nothing.  */
288130561Sobrien  tg_lineno
289130561Sobrien};
290130561Sobrien
29133965Sjdp/* Print out the generic debugging information recorded in dhandle.  */
29233965Sjdp
293130561Sobrienbfd_boolean
294130561Sobrienprint_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms,
295130561Sobrien		      void *demangler, bfd_boolean as_tags)
29633965Sjdp{
29733965Sjdp  struct pr_handle info;
29833965Sjdp
29933965Sjdp  info.f = f;
30033965Sjdp  info.indent = 0;
30133965Sjdp  info.stack = NULL;
30233965Sjdp  info.parameter = 0;
303130561Sobrien  info.filename = NULL;
304130561Sobrien  info.abfd = abfd;
305130561Sobrien  info.syms = syms;
306130561Sobrien  info.demangler = demangler;
30733965Sjdp
308130561Sobrien  if (as_tags)
309130561Sobrien    {
310130561Sobrien      fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f);
311130561Sobrien      fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f);
312130561Sobrien      fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f);
313130561Sobrien      fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f);
314130561Sobrien    }
315130561Sobrien
316130561Sobrien  return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info)
317130561Sobrien    : debug_write (dhandle, &pr_fns, (void *) & info);
31833965Sjdp}
31933965Sjdp
32033965Sjdp/* Indent to the current indentation level.  */
32133965Sjdp
32233965Sjdpstatic void
323130561Sobrienindent (struct pr_handle *info)
32433965Sjdp{
32533965Sjdp  unsigned int i;
32633965Sjdp
32733965Sjdp  for (i = 0; i < info->indent; i++)
32833965Sjdp    putc (' ', info->f);
32933965Sjdp}
33033965Sjdp
33133965Sjdp/* Push a type on the type stack.  */
33233965Sjdp
333130561Sobrienstatic bfd_boolean
334130561Sobrienpush_type (struct pr_handle *info, const char *type)
33533965Sjdp{
33633965Sjdp  struct pr_stack *n;
33733965Sjdp
33833965Sjdp  if (type == NULL)
339130561Sobrien    return FALSE;
34033965Sjdp
34133965Sjdp  n = (struct pr_stack *) xmalloc (sizeof *n);
34233965Sjdp  memset (n, 0, sizeof *n);
34333965Sjdp
34433965Sjdp  n->type = xstrdup (type);
34533965Sjdp  n->visibility = DEBUG_VISIBILITY_IGNORE;
34633965Sjdp  n->method = NULL;
34733965Sjdp  n->next = info->stack;
34833965Sjdp  info->stack = n;
34933965Sjdp
350130561Sobrien  return TRUE;
35133965Sjdp}
35233965Sjdp
35333965Sjdp/* Prepend a string onto the type on the top of the type stack.  */
35433965Sjdp
355130561Sobrienstatic bfd_boolean
356130561Sobrienprepend_type (struct pr_handle *info, const char *s)
35733965Sjdp{
35833965Sjdp  char *n;
35933965Sjdp
36033965Sjdp  assert (info->stack != NULL);
36133965Sjdp
36233965Sjdp  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
36333965Sjdp  sprintf (n, "%s%s", s, info->stack->type);
36433965Sjdp  free (info->stack->type);
36533965Sjdp  info->stack->type = n;
36633965Sjdp
367130561Sobrien  return TRUE;
36833965Sjdp}
36933965Sjdp
37033965Sjdp/* Append a string to the type on the top of the type stack.  */
37133965Sjdp
372130561Sobrienstatic bfd_boolean
373130561Sobrienappend_type (struct pr_handle *info, const char *s)
37433965Sjdp{
37533965Sjdp  unsigned int len;
37633965Sjdp
37733965Sjdp  if (s == NULL)
378130561Sobrien    return FALSE;
37933965Sjdp
38033965Sjdp  assert (info->stack != NULL);
38133965Sjdp
38233965Sjdp  len = strlen (info->stack->type);
38333965Sjdp  info->stack->type = (char *) xrealloc (info->stack->type,
38433965Sjdp					 len + strlen (s) + 1);
38533965Sjdp  strcpy (info->stack->type + len, s);
38633965Sjdp
387130561Sobrien  return TRUE;
38833965Sjdp}
38933965Sjdp
390130561Sobrien/* Append a string to the parents on the top of the type stack.  */
391130561Sobrien
392130561Sobrienstatic bfd_boolean
393130561Sobrienappend_parent (struct pr_handle *info, const char *s)
394130561Sobrien{
395130561Sobrien  unsigned int len;
396130561Sobrien
397130561Sobrien  if (s == NULL)
398130561Sobrien    return FALSE;
399130561Sobrien
400130561Sobrien  assert (info->stack != NULL);
401130561Sobrien
402130561Sobrien  len = info->stack->parents ? strlen (info->stack->parents) : 0;
403130561Sobrien  info->stack->parents = (char *) xrealloc (info->stack->parents,
404130561Sobrien					    len + strlen (s) + 1);
405130561Sobrien  strcpy (info->stack->parents + len, s);
406130561Sobrien
407130561Sobrien  return TRUE;
408130561Sobrien}
409130561Sobrien
41033965Sjdp/* We use an underscore to indicate where the name should go in a type
41133965Sjdp   string.  This function substitutes a string for the underscore.  If
41233965Sjdp   there is no underscore, the name follows the type.  */
41333965Sjdp
414130561Sobrienstatic bfd_boolean
415130561Sobriensubstitute_type (struct pr_handle *info, const char *s)
41633965Sjdp{
41733965Sjdp  char *u;
41833965Sjdp
41933965Sjdp  assert (info->stack != NULL);
42033965Sjdp
42133965Sjdp  u = strchr (info->stack->type, '|');
42233965Sjdp  if (u != NULL)
42333965Sjdp    {
42433965Sjdp      char *n;
42533965Sjdp
42633965Sjdp      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
42733965Sjdp
42833965Sjdp      memcpy (n, info->stack->type, u - info->stack->type);
42933965Sjdp      strcpy (n + (u - info->stack->type), s);
43033965Sjdp      strcat (n, u + 1);
43133965Sjdp
43233965Sjdp      free (info->stack->type);
43333965Sjdp      info->stack->type = n;
43433965Sjdp
435130561Sobrien      return TRUE;
43633965Sjdp    }
43733965Sjdp
43833965Sjdp  if (strchr (s, '|') != NULL
43933965Sjdp      && (strchr (info->stack->type, '{') != NULL
44033965Sjdp	  || strchr (info->stack->type, '(') != NULL))
44133965Sjdp    {
44233965Sjdp      if (! prepend_type (info, "(")
44333965Sjdp	  || ! append_type (info, ")"))
444130561Sobrien	return FALSE;
44533965Sjdp    }
44633965Sjdp
44733965Sjdp  if (*s == '\0')
448130561Sobrien    return TRUE;
44933965Sjdp
45033965Sjdp  return (append_type (info, " ")
45133965Sjdp	  && append_type (info, s));
45233965Sjdp}
45333965Sjdp
45433965Sjdp/* Indent the type at the top of the stack by appending spaces.  */
45533965Sjdp
456130561Sobrienstatic bfd_boolean
457130561Sobrienindent_type (struct pr_handle *info)
45833965Sjdp{
45933965Sjdp  unsigned int i;
46033965Sjdp
46133965Sjdp  for (i = 0; i < info->indent; i++)
46233965Sjdp    {
46333965Sjdp      if (! append_type (info, " "))
464130561Sobrien	return FALSE;
46533965Sjdp    }
46633965Sjdp
467130561Sobrien  return TRUE;
46833965Sjdp}
46933965Sjdp
47033965Sjdp/* Pop a type from the type stack.  */
47133965Sjdp
47233965Sjdpstatic char *
473130561Sobrienpop_type (struct pr_handle *info)
47433965Sjdp{
47533965Sjdp  struct pr_stack *o;
47633965Sjdp  char *ret;
47733965Sjdp
47833965Sjdp  assert (info->stack != NULL);
47933965Sjdp
48033965Sjdp  o = info->stack;
48133965Sjdp  info->stack = o->next;
48233965Sjdp  ret = o->type;
48333965Sjdp  free (o);
48433965Sjdp
48533965Sjdp  return ret;
48633965Sjdp}
48733965Sjdp
48833965Sjdp/* Print a VMA value into a string.  */
48933965Sjdp
49033965Sjdpstatic void
491130561Sobrienprint_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp)
49233965Sjdp{
49333965Sjdp  if (sizeof (vma) <= sizeof (unsigned long))
49433965Sjdp    {
49533965Sjdp      if (hexp)
49633965Sjdp	sprintf (buf, "0x%lx", (unsigned long) vma);
49733965Sjdp      else if (unsignedp)
49833965Sjdp	sprintf (buf, "%lu", (unsigned long) vma);
49933965Sjdp      else
50033965Sjdp	sprintf (buf, "%ld", (long) vma);
50133965Sjdp    }
50233965Sjdp  else
50333965Sjdp    {
50433965Sjdp      buf[0] = '0';
50533965Sjdp      buf[1] = 'x';
50633965Sjdp      sprintf_vma (buf + 2, vma);
50733965Sjdp    }
50833965Sjdp}
50933965Sjdp
51033965Sjdp/* Start a new compilation unit.  */
51133965Sjdp
512130561Sobrienstatic bfd_boolean
513130561Sobrienpr_start_compilation_unit (void *p, const char *filename)
51433965Sjdp{
51533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
51633965Sjdp
51733965Sjdp  assert (info->indent == 0);
51833965Sjdp
51933965Sjdp  fprintf (info->f, "%s:\n", filename);
52033965Sjdp
521130561Sobrien  return TRUE;
52233965Sjdp}
52333965Sjdp
52433965Sjdp/* Start a source file within a compilation unit.  */
52533965Sjdp
526130561Sobrienstatic bfd_boolean
527130561Sobrienpr_start_source (void *p, const char *filename)
52833965Sjdp{
52933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
53033965Sjdp
53133965Sjdp  assert (info->indent == 0);
53233965Sjdp
53333965Sjdp  fprintf (info->f, " %s:\n", filename);
53433965Sjdp
535130561Sobrien  return TRUE;
53633965Sjdp}
53733965Sjdp
53833965Sjdp/* Push an empty type onto the type stack.  */
53933965Sjdp
540130561Sobrienstatic bfd_boolean
541130561Sobrienpr_empty_type (void *p)
54233965Sjdp{
54333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
54433965Sjdp
54533965Sjdp  return push_type (info, "<undefined>");
54633965Sjdp}
54733965Sjdp
54833965Sjdp/* Push a void type onto the type stack.  */
54933965Sjdp
550130561Sobrienstatic bfd_boolean
551130561Sobrienpr_void_type (void *p)
55233965Sjdp{
55333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
55433965Sjdp
55533965Sjdp  return push_type (info, "void");
55633965Sjdp}
55733965Sjdp
55833965Sjdp/* Push an integer type onto the type stack.  */
55933965Sjdp
560130561Sobrienstatic bfd_boolean
561130561Sobrienpr_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
56233965Sjdp{
56333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
56433965Sjdp  char ab[10];
56533965Sjdp
56633965Sjdp  sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
56733965Sjdp  return push_type (info, ab);
56833965Sjdp}
56933965Sjdp
57033965Sjdp/* Push a floating type onto the type stack.  */
57133965Sjdp
572130561Sobrienstatic bfd_boolean
573130561Sobrienpr_float_type (void *p, unsigned int size)
57433965Sjdp{
57533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
57633965Sjdp  char ab[10];
57733965Sjdp
57833965Sjdp  if (size == 4)
57933965Sjdp    return push_type (info, "float");
58033965Sjdp  else if (size == 8)
58133965Sjdp    return push_type (info, "double");
58233965Sjdp
58333965Sjdp  sprintf (ab, "float%d", size * 8);
58433965Sjdp  return push_type (info, ab);
58533965Sjdp}
58633965Sjdp
58733965Sjdp/* Push a complex type onto the type stack.  */
58833965Sjdp
589130561Sobrienstatic bfd_boolean
590130561Sobrienpr_complex_type (void *p, unsigned int size)
59133965Sjdp{
59233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
59333965Sjdp
59433965Sjdp  if (! pr_float_type (p, size))
595130561Sobrien    return FALSE;
59633965Sjdp
59733965Sjdp  return prepend_type (info, "complex ");
59833965Sjdp}
59933965Sjdp
600130561Sobrien/* Push a bfd_boolean type onto the type stack.  */
60133965Sjdp
602130561Sobrienstatic bfd_boolean
603130561Sobrienpr_bool_type (void *p, unsigned int size)
60433965Sjdp{
60533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
60633965Sjdp  char ab[10];
60733965Sjdp
60833965Sjdp  sprintf (ab, "bool%d", size * 8);
60933965Sjdp
61033965Sjdp  return push_type (info, ab);
61133965Sjdp}
61233965Sjdp
61333965Sjdp/* Push an enum type onto the type stack.  */
61433965Sjdp
615130561Sobrienstatic bfd_boolean
616130561Sobrienpr_enum_type (void *p, const char *tag, const char **names,
617130561Sobrien	      bfd_signed_vma *values)
61833965Sjdp{
61933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
62033965Sjdp  unsigned int i;
62133965Sjdp  bfd_signed_vma val;
62233965Sjdp
62333965Sjdp  if (! push_type (info, "enum "))
624130561Sobrien    return FALSE;
62533965Sjdp  if (tag != NULL)
62633965Sjdp    {
62733965Sjdp      if (! append_type (info, tag)
62833965Sjdp	  || ! append_type (info, " "))
629130561Sobrien	return FALSE;
63033965Sjdp    }
63133965Sjdp  if (! append_type (info, "{ "))
632130561Sobrien    return FALSE;
63333965Sjdp
63433965Sjdp  if (names == NULL)
63533965Sjdp    {
63633965Sjdp      if (! append_type (info, "/* undefined */"))
637130561Sobrien	return FALSE;
63833965Sjdp    }
63933965Sjdp  else
64033965Sjdp    {
64133965Sjdp      val = 0;
64233965Sjdp      for (i = 0; names[i] != NULL; i++)
64333965Sjdp	{
64433965Sjdp	  if (i > 0)
64533965Sjdp	    {
64633965Sjdp	      if (! append_type (info, ", "))
647130561Sobrien		return FALSE;
64833965Sjdp	    }
64933965Sjdp
65033965Sjdp	  if (! append_type (info, names[i]))
651130561Sobrien	    return FALSE;
65233965Sjdp
65333965Sjdp	  if (values[i] != val)
65433965Sjdp	    {
65533965Sjdp	      char ab[20];
65633965Sjdp
657130561Sobrien	      print_vma (values[i], ab, FALSE, FALSE);
65833965Sjdp	      if (! append_type (info, " = ")
65933965Sjdp		  || ! append_type (info, ab))
660130561Sobrien		return FALSE;
66133965Sjdp	      val = values[i];
66233965Sjdp	    }
66333965Sjdp
66433965Sjdp	  ++val;
66533965Sjdp	}
66633965Sjdp    }
66733965Sjdp
66833965Sjdp  return append_type (info, " }");
66933965Sjdp}
67033965Sjdp
67133965Sjdp/* Turn the top type on the stack into a pointer.  */
67233965Sjdp
673130561Sobrienstatic bfd_boolean
674130561Sobrienpr_pointer_type (void *p)
67533965Sjdp{
67633965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
67733965Sjdp  char *s;
67833965Sjdp
67933965Sjdp  assert (info->stack != NULL);
68033965Sjdp
68133965Sjdp  s = strchr (info->stack->type, '|');
68233965Sjdp  if (s != NULL && s[1] == '[')
68333965Sjdp    return substitute_type (info, "(*|)");
68433965Sjdp  return substitute_type (info, "*|");
68533965Sjdp}
68633965Sjdp
68733965Sjdp/* Turn the top type on the stack into a function returning that type.  */
68833965Sjdp
689130561Sobrienstatic bfd_boolean
690130561Sobrienpr_function_type (void *p, int argcount, bfd_boolean varargs)
69133965Sjdp{
69233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
69333965Sjdp  char **arg_types;
69433965Sjdp  unsigned int len;
69533965Sjdp  char *s;
69633965Sjdp
69733965Sjdp  assert (info->stack != NULL);
69833965Sjdp
69933965Sjdp  len = 10;
70033965Sjdp
70133965Sjdp  if (argcount <= 0)
70233965Sjdp    {
70333965Sjdp      arg_types = NULL;
70433965Sjdp      len += 15;
70533965Sjdp    }
70633965Sjdp  else
70733965Sjdp    {
70833965Sjdp      int i;
70933965Sjdp
71033965Sjdp      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
71133965Sjdp      for (i = argcount - 1; i >= 0; i--)
71233965Sjdp	{
71333965Sjdp	  if (! substitute_type (info, ""))
714130561Sobrien	    return FALSE;
71533965Sjdp	  arg_types[i] = pop_type (info);
71633965Sjdp	  if (arg_types[i] == NULL)
717130561Sobrien	    return FALSE;
71833965Sjdp	  len += strlen (arg_types[i]) + 2;
71933965Sjdp	}
72033965Sjdp      if (varargs)
72133965Sjdp	len += 5;
72233965Sjdp    }
72333965Sjdp
72433965Sjdp  /* Now the return type is on the top of the stack.  */
72533965Sjdp
726218822Sdim  s = xmalloc (len);
727218822Sdim  LITSTRCPY (s, "(|) (");
72833965Sjdp
72933965Sjdp  if (argcount < 0)
73033965Sjdp    strcat (s, "/* unknown */");
73133965Sjdp  else
73233965Sjdp    {
73333965Sjdp      int i;
73433965Sjdp
73533965Sjdp      for (i = 0; i < argcount; i++)
73633965Sjdp	{
73733965Sjdp	  if (i > 0)
73833965Sjdp	    strcat (s, ", ");
73933965Sjdp	  strcat (s, arg_types[i]);
74033965Sjdp	}
74133965Sjdp      if (varargs)
74233965Sjdp	{
74333965Sjdp	  if (i > 0)
74433965Sjdp	    strcat (s, ", ");
74533965Sjdp	  strcat (s, "...");
74633965Sjdp	}
74733965Sjdp      if (argcount > 0)
74833965Sjdp	free (arg_types);
74933965Sjdp    }
75033965Sjdp
75133965Sjdp  strcat (s, ")");
75233965Sjdp
75333965Sjdp  if (! substitute_type (info, s))
754130561Sobrien    return FALSE;
75533965Sjdp
75633965Sjdp  free (s);
75733965Sjdp
758130561Sobrien  return TRUE;
75933965Sjdp}
76033965Sjdp
76133965Sjdp/* Turn the top type on the stack into a reference to that type.  */
76233965Sjdp
763130561Sobrienstatic bfd_boolean
764130561Sobrienpr_reference_type (void *p)
76533965Sjdp{
76633965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
76733965Sjdp
76833965Sjdp  assert (info->stack != NULL);
76933965Sjdp
77033965Sjdp  return substitute_type (info, "&|");
77133965Sjdp}
77233965Sjdp
77333965Sjdp/* Make a range type.  */
77433965Sjdp
775130561Sobrienstatic bfd_boolean
776130561Sobrienpr_range_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper)
77733965Sjdp{
77833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
77933965Sjdp  char abl[20], abu[20];
78033965Sjdp
78133965Sjdp  assert (info->stack != NULL);
78233965Sjdp
78333965Sjdp  if (! substitute_type (info, ""))
784130561Sobrien    return FALSE;
78533965Sjdp
786130561Sobrien  print_vma (lower, abl, FALSE, FALSE);
787130561Sobrien  print_vma (upper, abu, FALSE, FALSE);
78833965Sjdp
78933965Sjdp  return (prepend_type (info, "range (")
79033965Sjdp	  && append_type (info, "):")
79133965Sjdp	  && append_type (info, abl)
79233965Sjdp	  && append_type (info, ":")
79333965Sjdp	  && append_type (info, abu));
79433965Sjdp}
79533965Sjdp
79633965Sjdp/* Make an array type.  */
79733965Sjdp
798130561Sobrienstatic bfd_boolean
799130561Sobrienpr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper,
800130561Sobrien	       bfd_boolean stringp)
80133965Sjdp{
80233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
80333965Sjdp  char *range_type;
80433965Sjdp  char abl[20], abu[20], ab[50];
80533965Sjdp
80633965Sjdp  range_type = pop_type (info);
80733965Sjdp  if (range_type == NULL)
808130561Sobrien    return FALSE;
80933965Sjdp
81033965Sjdp  if (lower == 0)
81133965Sjdp    {
81233965Sjdp      if (upper == -1)
81333965Sjdp	sprintf (ab, "|[]");
81433965Sjdp      else
81533965Sjdp	{
816130561Sobrien	  print_vma (upper + 1, abu, FALSE, FALSE);
81733965Sjdp	  sprintf (ab, "|[%s]", abu);
81833965Sjdp	}
81933965Sjdp    }
82033965Sjdp  else
82133965Sjdp    {
822130561Sobrien      print_vma (lower, abl, FALSE, FALSE);
823130561Sobrien      print_vma (upper, abu, FALSE, FALSE);
82433965Sjdp      sprintf (ab, "|[%s:%s]", abl, abu);
82533965Sjdp    }
82633965Sjdp
82733965Sjdp  if (! substitute_type (info, ab))
828130561Sobrien    return FALSE;
82933965Sjdp
83033965Sjdp  if (strcmp (range_type, "int") != 0)
83133965Sjdp    {
83233965Sjdp      if (! append_type (info, ":")
83333965Sjdp	  || ! append_type (info, range_type))
834130561Sobrien	return FALSE;
83533965Sjdp    }
83633965Sjdp
83733965Sjdp  if (stringp)
83833965Sjdp    {
83933965Sjdp      if (! append_type (info, " /* string */"))
840130561Sobrien	return FALSE;
84133965Sjdp    }
84233965Sjdp
843130561Sobrien  return TRUE;
84433965Sjdp}
84533965Sjdp
84633965Sjdp/* Make a set type.  */
84733965Sjdp
848130561Sobrienstatic bfd_boolean
849130561Sobrienpr_set_type (void *p, bfd_boolean bitstringp)
85033965Sjdp{
85133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
85233965Sjdp
85333965Sjdp  if (! substitute_type (info, ""))
854130561Sobrien    return FALSE;
85533965Sjdp
85633965Sjdp  if (! prepend_type (info, "set { ")
85733965Sjdp      || ! append_type (info, " }"))
858130561Sobrien    return FALSE;
85933965Sjdp
86033965Sjdp  if (bitstringp)
86133965Sjdp    {
86233965Sjdp      if (! append_type (info, "/* bitstring */"))
863130561Sobrien	return FALSE;
86433965Sjdp    }
86533965Sjdp
866130561Sobrien  return TRUE;
86733965Sjdp}
86833965Sjdp
86933965Sjdp/* Make an offset type.  */
87033965Sjdp
871130561Sobrienstatic bfd_boolean
872130561Sobrienpr_offset_type (void *p)
87333965Sjdp{
87433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
87533965Sjdp  char *t;
87633965Sjdp
87733965Sjdp  if (! substitute_type (info, ""))
878130561Sobrien    return FALSE;
87933965Sjdp
88033965Sjdp  t = pop_type (info);
88133965Sjdp  if (t == NULL)
882130561Sobrien    return FALSE;
88333965Sjdp
88433965Sjdp  return (substitute_type (info, "")
88533965Sjdp	  && prepend_type (info, " ")
88633965Sjdp	  && prepend_type (info, t)
88733965Sjdp	  && append_type (info, "::|"));
88833965Sjdp}
88933965Sjdp
89033965Sjdp/* Make a method type.  */
89133965Sjdp
892130561Sobrienstatic bfd_boolean
893130561Sobrienpr_method_type (void *p, bfd_boolean domain, int argcount, bfd_boolean varargs)
89433965Sjdp{
89533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
89633965Sjdp  unsigned int len;
89733965Sjdp  char *domain_type;
89833965Sjdp  char **arg_types;
89933965Sjdp  char *s;
90033965Sjdp
90133965Sjdp  len = 10;
90233965Sjdp
90333965Sjdp  if (! domain)
90433965Sjdp    domain_type = NULL;
90533965Sjdp  else
90633965Sjdp    {
90733965Sjdp      if (! substitute_type (info, ""))
908130561Sobrien	return FALSE;
90933965Sjdp      domain_type = pop_type (info);
91033965Sjdp      if (domain_type == NULL)
911130561Sobrien	return FALSE;
912218822Sdim      if (CONST_STRNEQ (domain_type, "class ")
91333965Sjdp	  && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
91433965Sjdp	domain_type += sizeof "class " - 1;
915218822Sdim      else if (CONST_STRNEQ (domain_type, "union class ")
91633965Sjdp	       && (strchr (domain_type + sizeof "union class " - 1, ' ')
91733965Sjdp		   == NULL))
91833965Sjdp	domain_type += sizeof "union class " - 1;
91933965Sjdp      len += strlen (domain_type);
92033965Sjdp    }
92133965Sjdp
92233965Sjdp  if (argcount <= 0)
92333965Sjdp    {
92433965Sjdp      arg_types = NULL;
92533965Sjdp      len += 15;
92633965Sjdp    }
92733965Sjdp  else
92833965Sjdp    {
92933965Sjdp      int i;
93033965Sjdp
93133965Sjdp      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
93233965Sjdp      for (i = argcount - 1; i >= 0; i--)
93333965Sjdp	{
93433965Sjdp	  if (! substitute_type (info, ""))
935130561Sobrien	    return FALSE;
93633965Sjdp	  arg_types[i] = pop_type (info);
93733965Sjdp	  if (arg_types[i] == NULL)
938130561Sobrien	    return FALSE;
93933965Sjdp	  len += strlen (arg_types[i]) + 2;
94033965Sjdp	}
94133965Sjdp      if (varargs)
94233965Sjdp	len += 5;
94333965Sjdp    }
94433965Sjdp
94533965Sjdp  /* Now the return type is on the top of the stack.  */
94633965Sjdp
94733965Sjdp  s = (char *) xmalloc (len);
94833965Sjdp  if (! domain)
94933965Sjdp    *s = '\0';
95033965Sjdp  else
95133965Sjdp    strcpy (s, domain_type);
95233965Sjdp  strcat (s, "::| (");
95333965Sjdp
95433965Sjdp  if (argcount < 0)
95533965Sjdp    strcat (s, "/* unknown */");
95633965Sjdp  else
95733965Sjdp    {
95833965Sjdp      int i;
95933965Sjdp
96033965Sjdp      for (i = 0; i < argcount; i++)
96133965Sjdp	{
96233965Sjdp	  if (i > 0)
96333965Sjdp	    strcat (s, ", ");
96433965Sjdp	  strcat (s, arg_types[i]);
96533965Sjdp	}
96633965Sjdp      if (varargs)
96733965Sjdp	{
96833965Sjdp	  if (i > 0)
96933965Sjdp	    strcat (s, ", ");
97033965Sjdp	  strcat (s, "...");
97133965Sjdp	}
97233965Sjdp      if (argcount > 0)
97333965Sjdp	free (arg_types);
97433965Sjdp    }
97533965Sjdp
97633965Sjdp  strcat (s, ")");
97733965Sjdp
97833965Sjdp  if (! substitute_type (info, s))
979130561Sobrien    return FALSE;
98033965Sjdp
98133965Sjdp  free (s);
98233965Sjdp
983130561Sobrien  return TRUE;
98433965Sjdp}
98533965Sjdp
98633965Sjdp/* Make a const qualified type.  */
98733965Sjdp
988130561Sobrienstatic bfd_boolean
989130561Sobrienpr_const_type (void *p)
99033965Sjdp{
99133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
99233965Sjdp
99333965Sjdp  return substitute_type (info, "const |");
99433965Sjdp}
99533965Sjdp
99633965Sjdp/* Make a volatile qualified type.  */
99733965Sjdp
998130561Sobrienstatic bfd_boolean
999130561Sobrienpr_volatile_type (void *p)
100033965Sjdp{
100133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
100233965Sjdp
100333965Sjdp  return substitute_type (info, "volatile |");
100433965Sjdp}
100533965Sjdp
100633965Sjdp/* Start accumulating a struct type.  */
100733965Sjdp
1008130561Sobrienstatic bfd_boolean
1009130561Sobrienpr_start_struct_type (void *p, const char *tag, unsigned int id,
1010130561Sobrien		      bfd_boolean structp, unsigned int size)
101133965Sjdp{
101233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
101333965Sjdp
101433965Sjdp  info->indent += 2;
101533965Sjdp
101633965Sjdp  if (! push_type (info, structp ? "struct " : "union "))
1017130561Sobrien    return FALSE;
101833965Sjdp  if (tag != NULL)
101933965Sjdp    {
102033965Sjdp      if (! append_type (info, tag))
1021130561Sobrien	return FALSE;
102233965Sjdp    }
102333965Sjdp  else
102433965Sjdp    {
102533965Sjdp      char idbuf[20];
102633965Sjdp
102733965Sjdp      sprintf (idbuf, "%%anon%u", id);
102833965Sjdp      if (! append_type (info, idbuf))
1029130561Sobrien	return FALSE;
103033965Sjdp    }
103133965Sjdp
103233965Sjdp  if (! append_type (info, " {"))
1033130561Sobrien    return FALSE;
103433965Sjdp  if (size != 0 || tag != NULL)
103533965Sjdp    {
103633965Sjdp      char ab[30];
103733965Sjdp
103833965Sjdp      if (! append_type (info, " /*"))
1039130561Sobrien	return FALSE;
104033965Sjdp
104133965Sjdp      if (size != 0)
104233965Sjdp	{
104333965Sjdp	  sprintf (ab, " size %u", size);
104433965Sjdp	  if (! append_type (info, ab))
1045130561Sobrien	    return FALSE;
104633965Sjdp	}
104733965Sjdp      if (tag != NULL)
104833965Sjdp	{
104933965Sjdp	  sprintf (ab, " id %u", id);
105033965Sjdp	  if (! append_type (info, ab))
1051130561Sobrien	    return FALSE;
105233965Sjdp	}
105333965Sjdp      if (! append_type (info, " */"))
1054130561Sobrien	return FALSE;
105533965Sjdp    }
105633965Sjdp  if (! append_type (info, "\n"))
1057130561Sobrien    return FALSE;
105833965Sjdp
105933965Sjdp  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
106033965Sjdp
106133965Sjdp  return indent_type (info);
106233965Sjdp}
106333965Sjdp
106433965Sjdp/* Output the visibility of a field in a struct.  */
106533965Sjdp
1066130561Sobrienstatic bfd_boolean
1067130561Sobrienpr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
106833965Sjdp{
106960484Sobrien  const char *s = NULL;
107033965Sjdp  char *t;
107133965Sjdp  unsigned int len;
107233965Sjdp
107333965Sjdp  assert (info->stack != NULL);
107433965Sjdp
107533965Sjdp  if (info->stack->visibility == visibility)
1076130561Sobrien    return TRUE;
107733965Sjdp
107833965Sjdp  switch (visibility)
107933965Sjdp    {
108033965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
108133965Sjdp      s = "public";
108233965Sjdp      break;
108333965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
108433965Sjdp      s = "private";
108533965Sjdp      break;
108633965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
108733965Sjdp      s = "protected";
108833965Sjdp      break;
108933965Sjdp    case DEBUG_VISIBILITY_IGNORE:
109033965Sjdp      s = "/* ignore */";
109133965Sjdp      break;
109233965Sjdp    default:
109333965Sjdp      abort ();
1094130561Sobrien      return FALSE;
109533965Sjdp    }
109633965Sjdp
109733965Sjdp  /* Trim off a trailing space in the struct string, to make the
109833965Sjdp     output look a bit better, then stick on the visibility string.  */
109933965Sjdp
110033965Sjdp  t = info->stack->type;
110133965Sjdp  len = strlen (t);
110233965Sjdp  assert (t[len - 1] == ' ');
110333965Sjdp  t[len - 1] = '\0';
110433965Sjdp
110533965Sjdp  if (! append_type (info, s)
110633965Sjdp      || ! append_type (info, ":\n")
110733965Sjdp      || ! indent_type (info))
1108130561Sobrien    return FALSE;
110933965Sjdp
111033965Sjdp  info->stack->visibility = visibility;
111133965Sjdp
1112130561Sobrien  return TRUE;
111333965Sjdp}
111433965Sjdp
111533965Sjdp/* Add a field to a struct type.  */
111633965Sjdp
1117130561Sobrienstatic bfd_boolean
1118130561Sobrienpr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
1119130561Sobrien		 enum debug_visibility visibility)
112033965Sjdp{
112133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
112233965Sjdp  char ab[20];
112333965Sjdp  char *t;
112433965Sjdp
112533965Sjdp  if (! substitute_type (info, name))
1126130561Sobrien    return FALSE;
112733965Sjdp
112833965Sjdp  if (! append_type (info, "; /* "))
1129130561Sobrien    return FALSE;
113033965Sjdp
113133965Sjdp  if (bitsize != 0)
113233965Sjdp    {
1133130561Sobrien      print_vma (bitsize, ab, TRUE, FALSE);
113433965Sjdp      if (! append_type (info, "bitsize ")
113533965Sjdp	  || ! append_type (info, ab)
113633965Sjdp	  || ! append_type (info, ", "))
1137130561Sobrien	return FALSE;
113833965Sjdp    }
113933965Sjdp
1140130561Sobrien  print_vma (bitpos, ab, TRUE, FALSE);
114133965Sjdp  if (! append_type (info, "bitpos ")
114233965Sjdp      || ! append_type (info, ab)
114333965Sjdp      || ! append_type (info, " */\n")
114433965Sjdp      || ! indent_type (info))
1145130561Sobrien    return FALSE;
114633965Sjdp
114733965Sjdp  t = pop_type (info);
114833965Sjdp  if (t == NULL)
1149130561Sobrien    return FALSE;
115033965Sjdp
115133965Sjdp  if (! pr_fix_visibility (info, visibility))
1152130561Sobrien    return FALSE;
115333965Sjdp
115433965Sjdp  return append_type (info, t);
115533965Sjdp}
115633965Sjdp
115733965Sjdp/* Finish a struct type.  */
115833965Sjdp
1159130561Sobrienstatic bfd_boolean
1160130561Sobrienpr_end_struct_type (void *p)
116133965Sjdp{
116233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
116333965Sjdp  char *s;
116433965Sjdp
116533965Sjdp  assert (info->stack != NULL);
116633965Sjdp  assert (info->indent >= 2);
116733965Sjdp
116833965Sjdp  info->indent -= 2;
116933965Sjdp
117033965Sjdp  /* Change the trailing indentation to have a close brace.  */
117133965Sjdp  s = info->stack->type + strlen (info->stack->type) - 2;
117233965Sjdp  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
117333965Sjdp
117433965Sjdp  *s++ = '}';
117533965Sjdp  *s = '\0';
117633965Sjdp
1177130561Sobrien  return TRUE;
117833965Sjdp}
117933965Sjdp
118033965Sjdp/* Start a class type.  */
118133965Sjdp
1182130561Sobrienstatic bfd_boolean
1183130561Sobrienpr_start_class_type (void *p, const char *tag, unsigned int id,
1184130561Sobrien		     bfd_boolean structp, unsigned int size,
1185130561Sobrien		     bfd_boolean vptr, bfd_boolean ownvptr)
118633965Sjdp{
118733965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
118833965Sjdp  char *tv = NULL;
118933965Sjdp
119033965Sjdp  info->indent += 2;
119133965Sjdp
119233965Sjdp  if (vptr && ! ownvptr)
119333965Sjdp    {
119433965Sjdp      tv = pop_type (info);
119533965Sjdp      if (tv == NULL)
1196130561Sobrien	return FALSE;
119733965Sjdp    }
119833965Sjdp
119933965Sjdp  if (! push_type (info, structp ? "class " : "union class "))
1200130561Sobrien    return FALSE;
120133965Sjdp  if (tag != NULL)
120233965Sjdp    {
120333965Sjdp      if (! append_type (info, tag))
1204130561Sobrien	return FALSE;
120533965Sjdp    }
120633965Sjdp  else
120733965Sjdp    {
120833965Sjdp      char idbuf[20];
120933965Sjdp
121033965Sjdp      sprintf (idbuf, "%%anon%u", id);
121133965Sjdp      if (! append_type (info, idbuf))
1212130561Sobrien	return FALSE;
121333965Sjdp    }
121433965Sjdp
121533965Sjdp  if (! append_type (info, " {"))
1216130561Sobrien    return FALSE;
121733965Sjdp  if (size != 0 || vptr || ownvptr || tag != NULL)
121833965Sjdp    {
121933965Sjdp      if (! append_type (info, " /*"))
1220130561Sobrien	return FALSE;
122133965Sjdp
122233965Sjdp      if (size != 0)
122333965Sjdp	{
122433965Sjdp	  char ab[20];
122533965Sjdp
122633965Sjdp	  sprintf (ab, "%u", size);
122733965Sjdp	  if (! append_type (info, " size ")
122833965Sjdp	      || ! append_type (info, ab))
1229130561Sobrien	    return FALSE;
123033965Sjdp	}
123133965Sjdp
123233965Sjdp      if (vptr)
123333965Sjdp	{
123433965Sjdp	  if (! append_type (info, " vtable "))
1235130561Sobrien	    return FALSE;
123633965Sjdp	  if (ownvptr)
123733965Sjdp	    {
123833965Sjdp	      if (! append_type (info, "self "))
1239130561Sobrien		return FALSE;
124033965Sjdp	    }
124133965Sjdp	  else
124233965Sjdp	    {
124333965Sjdp	      if (! append_type (info, tv)
124433965Sjdp		  || ! append_type (info, " "))
1245130561Sobrien		return FALSE;
124633965Sjdp	    }
124733965Sjdp	}
124833965Sjdp
124933965Sjdp      if (tag != NULL)
125033965Sjdp	{
125133965Sjdp	  char ab[30];
125233965Sjdp
125333965Sjdp	  sprintf (ab, " id %u", id);
125433965Sjdp	  if (! append_type (info, ab))
1255130561Sobrien	    return FALSE;
125633965Sjdp	}
125733965Sjdp
125833965Sjdp      if (! append_type (info, " */"))
1259130561Sobrien	return FALSE;
126033965Sjdp    }
126133965Sjdp
126233965Sjdp  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
126333965Sjdp
126433965Sjdp  return (append_type (info, "\n")
126533965Sjdp	  && indent_type (info));
126633965Sjdp}
126733965Sjdp
126833965Sjdp/* Add a static member to a class.  */
126933965Sjdp
1270130561Sobrienstatic bfd_boolean
1271130561Sobrienpr_class_static_member (void *p, const char *name, const char *physname,
1272130561Sobrien			enum debug_visibility visibility)
127333965Sjdp{
127433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
127533965Sjdp  char *t;
127633965Sjdp
127733965Sjdp  if (! substitute_type (info, name))
1278130561Sobrien    return FALSE;
127933965Sjdp
128033965Sjdp  if (! prepend_type (info, "static ")
128133965Sjdp      || ! append_type (info, "; /* ")
128233965Sjdp      || ! append_type (info, physname)
128333965Sjdp      || ! append_type (info, " */\n")
128433965Sjdp      || ! indent_type (info))
1285130561Sobrien    return FALSE;
128633965Sjdp
128733965Sjdp  t = pop_type (info);
128833965Sjdp  if (t == NULL)
1289130561Sobrien    return FALSE;
129033965Sjdp
129133965Sjdp  if (! pr_fix_visibility (info, visibility))
1292130561Sobrien    return FALSE;
129333965Sjdp
129433965Sjdp  return append_type (info, t);
129533965Sjdp}
129633965Sjdp
129733965Sjdp/* Add a base class to a class.  */
129833965Sjdp
1299130561Sobrienstatic bfd_boolean
1300130561Sobrienpr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
1301130561Sobrien		    enum debug_visibility visibility)
130233965Sjdp{
130333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
130433965Sjdp  char *t;
130533965Sjdp  const char *prefix;
130633965Sjdp  char ab[20];
130733965Sjdp  char *s, *l, *n;
130833965Sjdp
130933965Sjdp  assert (info->stack != NULL && info->stack->next != NULL);
131033965Sjdp
131133965Sjdp  if (! substitute_type (info, ""))
1312130561Sobrien    return FALSE;
131333965Sjdp
131433965Sjdp  t = pop_type (info);
131533965Sjdp  if (t == NULL)
1316130561Sobrien    return FALSE;
131733965Sjdp
1318218822Sdim  if (CONST_STRNEQ (t, "class "))
131933965Sjdp    t += sizeof "class " - 1;
132033965Sjdp
132133965Sjdp  /* Push it back on to take advantage of the prepend_type and
132233965Sjdp     append_type routines.  */
132333965Sjdp  if (! push_type (info, t))
1324130561Sobrien    return FALSE;
132533965Sjdp
132633965Sjdp  if (virtual)
132733965Sjdp    {
132833965Sjdp      if (! prepend_type (info, "virtual "))
1329130561Sobrien	return FALSE;
133033965Sjdp    }
133133965Sjdp
133233965Sjdp  switch (visibility)
133333965Sjdp    {
133433965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
133533965Sjdp      prefix = "public ";
133633965Sjdp      break;
133733965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
133833965Sjdp      prefix = "protected ";
133933965Sjdp      break;
134033965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
134133965Sjdp      prefix = "private ";
134233965Sjdp      break;
134333965Sjdp    default:
134433965Sjdp      prefix = "/* unknown visibility */ ";
134533965Sjdp      break;
134633965Sjdp    }
134733965Sjdp
134833965Sjdp  if (! prepend_type (info, prefix))
1349130561Sobrien    return FALSE;
135033965Sjdp
135133965Sjdp  if (bitpos != 0)
135233965Sjdp    {
1353130561Sobrien      print_vma (bitpos, ab, TRUE, FALSE);
135433965Sjdp      if (! append_type (info, " /* bitpos ")
135533965Sjdp	  || ! append_type (info, ab)
135633965Sjdp	  || ! append_type (info, " */"))
1357130561Sobrien	return FALSE;
135833965Sjdp    }
135933965Sjdp
136033965Sjdp  /* Now the top of the stack is something like "public A / * bitpos
136133965Sjdp     10 * /".  The next element on the stack is something like "class
136233965Sjdp     xx { / * size 8 * /\n...".  We want to substitute the top of the
136333965Sjdp     stack in before the {.  */
136433965Sjdp  s = strchr (info->stack->next->type, '{');
136533965Sjdp  assert (s != NULL);
136633965Sjdp  --s;
136733965Sjdp
136833965Sjdp  /* If there is already a ':', then we already have a baseclass, and
136933965Sjdp     we must append this one after a comma.  */
137033965Sjdp  for (l = info->stack->next->type; l != s; l++)
137133965Sjdp    if (*l == ':')
137233965Sjdp      break;
137333965Sjdp  if (! prepend_type (info, l == s ? " : " : ", "))
1374130561Sobrien    return FALSE;
137533965Sjdp
137633965Sjdp  t = pop_type (info);
137733965Sjdp  if (t == NULL)
1378130561Sobrien    return FALSE;
137933965Sjdp
138033965Sjdp  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
138133965Sjdp  memcpy (n, info->stack->type, s - info->stack->type);
138233965Sjdp  strcpy (n + (s - info->stack->type), t);
138333965Sjdp  strcat (n, s);
138433965Sjdp
138533965Sjdp  free (info->stack->type);
138633965Sjdp  info->stack->type = n;
138733965Sjdp
138833965Sjdp  free (t);
138933965Sjdp
1390130561Sobrien  return TRUE;
139133965Sjdp}
139233965Sjdp
139333965Sjdp/* Start adding a method to a class.  */
139433965Sjdp
1395130561Sobrienstatic bfd_boolean
1396130561Sobrienpr_class_start_method (void *p, const char *name)
139733965Sjdp{
139833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
139933965Sjdp
140033965Sjdp  assert (info->stack != NULL);
140133965Sjdp  info->stack->method = name;
1402130561Sobrien  return TRUE;
140333965Sjdp}
140433965Sjdp
140533965Sjdp/* Add a variant to a method.  */
140633965Sjdp
1407130561Sobrienstatic bfd_boolean
1408130561Sobrienpr_class_method_variant (void *p, const char *physname,
1409130561Sobrien			 enum debug_visibility visibility,
1410130561Sobrien			 bfd_boolean constp, bfd_boolean volatilep,
1411130561Sobrien			 bfd_vma voffset, bfd_boolean context)
141233965Sjdp{
141333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
141433965Sjdp  char *method_type;
141533965Sjdp  char *context_type;
141633965Sjdp
141733965Sjdp  assert (info->stack != NULL);
141833965Sjdp  assert (info->stack->next != NULL);
141933965Sjdp
142033965Sjdp  /* Put the const and volatile qualifiers on the type.  */
142133965Sjdp  if (volatilep)
142233965Sjdp    {
142333965Sjdp      if (! append_type (info, " volatile"))
1424130561Sobrien	return FALSE;
142533965Sjdp    }
142633965Sjdp  if (constp)
142733965Sjdp    {
142833965Sjdp      if (! append_type (info, " const"))
1429130561Sobrien	return FALSE;
143033965Sjdp    }
143133965Sjdp
143233965Sjdp  /* Stick the name of the method into its type.  */
143333965Sjdp  if (! substitute_type (info,
143433965Sjdp			 (context
143533965Sjdp			  ? info->stack->next->next->method
143633965Sjdp			  : info->stack->next->method)))
1437130561Sobrien    return FALSE;
143833965Sjdp
143933965Sjdp  /* Get the type.  */
144033965Sjdp  method_type = pop_type (info);
144133965Sjdp  if (method_type == NULL)
1442130561Sobrien    return FALSE;
144333965Sjdp
144433965Sjdp  /* Pull off the context type if there is one.  */
144533965Sjdp  if (! context)
144633965Sjdp    context_type = NULL;
144733965Sjdp  else
144833965Sjdp    {
144933965Sjdp      context_type = pop_type (info);
145033965Sjdp      if (context_type == NULL)
1451130561Sobrien	return FALSE;
145233965Sjdp    }
145333965Sjdp
145433965Sjdp  /* Now the top of the stack is the class.  */
145533965Sjdp
145633965Sjdp  if (! pr_fix_visibility (info, visibility))
1457130561Sobrien    return FALSE;
145833965Sjdp
145933965Sjdp  if (! append_type (info, method_type)
146033965Sjdp      || ! append_type (info, " /* ")
146133965Sjdp      || ! append_type (info, physname)
146233965Sjdp      || ! append_type (info, " "))
1463130561Sobrien    return FALSE;
146433965Sjdp  if (context || voffset != 0)
146533965Sjdp    {
146633965Sjdp      char ab[20];
146733965Sjdp
146833965Sjdp      if (context)
146933965Sjdp	{
147033965Sjdp	  if (! append_type (info, "context ")
147133965Sjdp	      || ! append_type (info, context_type)
147233965Sjdp	      || ! append_type (info, " "))
1473130561Sobrien	    return FALSE;
147433965Sjdp	}
1475130561Sobrien      print_vma (voffset, ab, TRUE, FALSE);
147633965Sjdp      if (! append_type (info, "voffset ")
147733965Sjdp	  || ! append_type (info, ab))
1478130561Sobrien	return FALSE;
147933965Sjdp    }
148033965Sjdp
148133965Sjdp  return (append_type (info, " */;\n")
148233965Sjdp	  && indent_type (info));
148333965Sjdp}
148433965Sjdp
148533965Sjdp/* Add a static variant to a method.  */
148633965Sjdp
1487130561Sobrienstatic bfd_boolean
1488130561Sobrienpr_class_static_method_variant (void *p, const char *physname,
1489130561Sobrien				enum debug_visibility visibility,
1490130561Sobrien				bfd_boolean constp, bfd_boolean volatilep)
149133965Sjdp{
149233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
149333965Sjdp  char *method_type;
149433965Sjdp
149533965Sjdp  assert (info->stack != NULL);
149633965Sjdp  assert (info->stack->next != NULL);
149733965Sjdp  assert (info->stack->next->method != NULL);
149833965Sjdp
149933965Sjdp  /* Put the const and volatile qualifiers on the type.  */
150033965Sjdp  if (volatilep)
150133965Sjdp    {
150233965Sjdp      if (! append_type (info, " volatile"))
1503130561Sobrien	return FALSE;
150433965Sjdp    }
150533965Sjdp  if (constp)
150633965Sjdp    {
150733965Sjdp      if (! append_type (info, " const"))
1508130561Sobrien	return FALSE;
150933965Sjdp    }
151033965Sjdp
151133965Sjdp  /* Mark it as static.  */
151233965Sjdp  if (! prepend_type (info, "static "))
1513130561Sobrien    return FALSE;
151433965Sjdp
151533965Sjdp  /* Stick the name of the method into its type.  */
151633965Sjdp  if (! substitute_type (info, info->stack->next->method))
1517130561Sobrien    return FALSE;
151833965Sjdp
151933965Sjdp  /* Get the type.  */
152033965Sjdp  method_type = pop_type (info);
152133965Sjdp  if (method_type == NULL)
1522130561Sobrien    return FALSE;
152333965Sjdp
152433965Sjdp  /* Now the top of the stack is the class.  */
152533965Sjdp
152633965Sjdp  if (! pr_fix_visibility (info, visibility))
1527130561Sobrien    return FALSE;
152833965Sjdp
152933965Sjdp  return (append_type (info, method_type)
153033965Sjdp	  && append_type (info, " /* ")
153133965Sjdp	  && append_type (info, physname)
153233965Sjdp	  && append_type (info, " */;\n")
153333965Sjdp	  && indent_type (info));
153433965Sjdp}
153533965Sjdp
153633965Sjdp/* Finish up a method.  */
153733965Sjdp
1538130561Sobrienstatic bfd_boolean
1539130561Sobrienpr_class_end_method (void *p)
154033965Sjdp{
154133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
154233965Sjdp
154333965Sjdp  info->stack->method = NULL;
1544130561Sobrien  return TRUE;
154533965Sjdp}
154633965Sjdp
154733965Sjdp/* Finish up a class.  */
154833965Sjdp
1549130561Sobrienstatic bfd_boolean
1550130561Sobrienpr_end_class_type (void *p)
155133965Sjdp{
155233965Sjdp  return pr_end_struct_type (p);
155333965Sjdp}
155433965Sjdp
155533965Sjdp/* Push a type on the stack using a typedef name.  */
155633965Sjdp
1557130561Sobrienstatic bfd_boolean
1558130561Sobrienpr_typedef_type (void *p, const char *name)
155933965Sjdp{
156033965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
156133965Sjdp
156233965Sjdp  return push_type (info, name);
156333965Sjdp}
156433965Sjdp
156533965Sjdp/* Push a type on the stack using a tag name.  */
156633965Sjdp
1567130561Sobrienstatic bfd_boolean
1568130561Sobrienpr_tag_type (void *p, const char *name, unsigned int id,
1569130561Sobrien	     enum debug_type_kind kind)
157033965Sjdp{
157133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
157233965Sjdp  const char *t, *tag;
157333965Sjdp  char idbuf[20];
157433965Sjdp
157533965Sjdp  switch (kind)
157633965Sjdp    {
157733965Sjdp    case DEBUG_KIND_STRUCT:
157833965Sjdp      t = "struct ";
157933965Sjdp      break;
158033965Sjdp    case DEBUG_KIND_UNION:
158133965Sjdp      t = "union ";
158233965Sjdp      break;
158333965Sjdp    case DEBUG_KIND_ENUM:
158433965Sjdp      t = "enum ";
158533965Sjdp      break;
158633965Sjdp    case DEBUG_KIND_CLASS:
158733965Sjdp      t = "class ";
158833965Sjdp      break;
158933965Sjdp    case DEBUG_KIND_UNION_CLASS:
159033965Sjdp      t = "union class ";
159133965Sjdp      break;
159233965Sjdp    default:
159333965Sjdp      abort ();
1594130561Sobrien      return FALSE;
159533965Sjdp    }
159633965Sjdp
159733965Sjdp  if (! push_type (info, t))
1598130561Sobrien    return FALSE;
159933965Sjdp  if (name != NULL)
160033965Sjdp    tag = name;
160133965Sjdp  else
160233965Sjdp    {
160333965Sjdp      sprintf (idbuf, "%%anon%u", id);
160433965Sjdp      tag = idbuf;
160533965Sjdp    }
160633965Sjdp
160733965Sjdp  if (! append_type (info, tag))
1608130561Sobrien    return FALSE;
160933965Sjdp  if (name != NULL && kind != DEBUG_KIND_ENUM)
161033965Sjdp    {
161133965Sjdp      sprintf (idbuf, " /* id %u */", id);
161233965Sjdp      if (! append_type (info, idbuf))
1613130561Sobrien	return FALSE;
161433965Sjdp    }
161533965Sjdp
1616130561Sobrien  return TRUE;
161733965Sjdp}
161833965Sjdp
161933965Sjdp/* Output a typedef.  */
162033965Sjdp
1621130561Sobrienstatic bfd_boolean
1622130561Sobrienpr_typdef (void *p, const char *name)
162333965Sjdp{
162433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
162533965Sjdp  char *s;
162633965Sjdp
162733965Sjdp  if (! substitute_type (info, name))
1628130561Sobrien    return FALSE;
162933965Sjdp
163033965Sjdp  s = pop_type (info);
163133965Sjdp  if (s == NULL)
1632130561Sobrien    return FALSE;
163333965Sjdp
163433965Sjdp  indent (info);
163533965Sjdp  fprintf (info->f, "typedef %s;\n", s);
163633965Sjdp
163733965Sjdp  free (s);
163833965Sjdp
1639130561Sobrien  return TRUE;
164033965Sjdp}
164133965Sjdp
164233965Sjdp/* Output a tag.  The tag should already be in the string on the
164333965Sjdp   stack, so all we have to do here is print it out.  */
164433965Sjdp
1645130561Sobrienstatic bfd_boolean
1646130561Sobrienpr_tag (void *p, const char *name ATTRIBUTE_UNUSED)
164733965Sjdp{
164833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
164933965Sjdp  char *t;
165033965Sjdp
165133965Sjdp  t = pop_type (info);
165233965Sjdp  if (t == NULL)
1653130561Sobrien    return FALSE;
165433965Sjdp
165533965Sjdp  indent (info);
165633965Sjdp  fprintf (info->f, "%s;\n", t);
165733965Sjdp
165833965Sjdp  free (t);
165933965Sjdp
1660130561Sobrien  return TRUE;
166133965Sjdp}
166233965Sjdp
166333965Sjdp/* Output an integer constant.  */
166433965Sjdp
1665130561Sobrienstatic bfd_boolean
1666130561Sobrienpr_int_constant (void *p, const char *name, bfd_vma val)
166733965Sjdp{
166833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
166933965Sjdp  char ab[20];
167033965Sjdp
167133965Sjdp  indent (info);
1672130561Sobrien  print_vma (val, ab, FALSE, FALSE);
167333965Sjdp  fprintf (info->f, "const int %s = %s;\n", name, ab);
1674130561Sobrien  return TRUE;
167533965Sjdp}
167633965Sjdp
167733965Sjdp/* Output a floating point constant.  */
167833965Sjdp
1679130561Sobrienstatic bfd_boolean
1680130561Sobrienpr_float_constant (void *p, const char *name, double val)
168133965Sjdp{
168233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
168333965Sjdp
168433965Sjdp  indent (info);
168533965Sjdp  fprintf (info->f, "const double %s = %g;\n", name, val);
1686130561Sobrien  return TRUE;
168733965Sjdp}
168833965Sjdp
168933965Sjdp/* Output a typed constant.  */
169033965Sjdp
1691130561Sobrienstatic bfd_boolean
1692130561Sobrienpr_typed_constant (void *p, const char *name, bfd_vma val)
169333965Sjdp{
169433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
169533965Sjdp  char *t;
169633965Sjdp  char ab[20];
169733965Sjdp
169833965Sjdp  t = pop_type (info);
169933965Sjdp  if (t == NULL)
1700130561Sobrien    return FALSE;
170133965Sjdp
170233965Sjdp  indent (info);
1703130561Sobrien  print_vma (val, ab, FALSE, FALSE);
170433965Sjdp  fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
170533965Sjdp
170633965Sjdp  free (t);
170733965Sjdp
1708130561Sobrien  return TRUE;
170933965Sjdp}
171033965Sjdp
171133965Sjdp/* Output a variable.  */
171233965Sjdp
1713130561Sobrienstatic bfd_boolean
1714130561Sobrienpr_variable (void *p, const char *name, enum debug_var_kind kind,
1715130561Sobrien	     bfd_vma val)
171633965Sjdp{
171733965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
171833965Sjdp  char *t;
171933965Sjdp  char ab[20];
172033965Sjdp
172133965Sjdp  if (! substitute_type (info, name))
1722130561Sobrien    return FALSE;
172333965Sjdp
172433965Sjdp  t = pop_type (info);
172533965Sjdp  if (t == NULL)
1726130561Sobrien    return FALSE;
172733965Sjdp
172833965Sjdp  indent (info);
172933965Sjdp  switch (kind)
173033965Sjdp    {
173133965Sjdp    case DEBUG_STATIC:
173233965Sjdp    case DEBUG_LOCAL_STATIC:
173333965Sjdp      fprintf (info->f, "static ");
173433965Sjdp      break;
173533965Sjdp    case DEBUG_REGISTER:
173633965Sjdp      fprintf (info->f, "register ");
173733965Sjdp      break;
173833965Sjdp    default:
173933965Sjdp      break;
174033965Sjdp    }
1741130561Sobrien  print_vma (val, ab, TRUE, TRUE);
174233965Sjdp  fprintf (info->f, "%s /* %s */;\n", t, ab);
174333965Sjdp
174433965Sjdp  free (t);
174533965Sjdp
1746130561Sobrien  return TRUE;
174733965Sjdp}
174833965Sjdp
174933965Sjdp/* Start outputting a function.  */
175033965Sjdp
1751130561Sobrienstatic bfd_boolean
1752130561Sobrienpr_start_function (void *p, const char *name, bfd_boolean global)
175333965Sjdp{
175433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
175533965Sjdp  char *t;
175633965Sjdp
175733965Sjdp  if (! substitute_type (info, name))
1758130561Sobrien    return FALSE;
175933965Sjdp
176033965Sjdp  t = pop_type (info);
176133965Sjdp  if (t == NULL)
1762130561Sobrien    return FALSE;
176333965Sjdp
176433965Sjdp  indent (info);
176533965Sjdp  if (! global)
176633965Sjdp    fprintf (info->f, "static ");
176733965Sjdp  fprintf (info->f, "%s (", t);
176833965Sjdp
176933965Sjdp  info->parameter = 1;
177033965Sjdp
1771130561Sobrien  return TRUE;
177233965Sjdp}
177333965Sjdp
177433965Sjdp/* Output a function parameter.  */
177533965Sjdp
1776130561Sobrienstatic bfd_boolean
1777130561Sobrienpr_function_parameter (void *p, const char *name,
1778130561Sobrien		       enum debug_parm_kind kind, bfd_vma val)
177933965Sjdp{
178033965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
178133965Sjdp  char *t;
178233965Sjdp  char ab[20];
178333965Sjdp
178433965Sjdp  if (kind == DEBUG_PARM_REFERENCE
178533965Sjdp      || kind == DEBUG_PARM_REF_REG)
178633965Sjdp    {
178733965Sjdp      if (! pr_reference_type (p))
1788130561Sobrien	return FALSE;
178933965Sjdp    }
179033965Sjdp
179133965Sjdp  if (! substitute_type (info, name))
1792130561Sobrien    return FALSE;
179333965Sjdp
179433965Sjdp  t = pop_type (info);
179533965Sjdp  if (t == NULL)
1796130561Sobrien    return FALSE;
179733965Sjdp
179833965Sjdp  if (info->parameter != 1)
179933965Sjdp    fprintf (info->f, ", ");
180033965Sjdp
180133965Sjdp  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
180233965Sjdp    fprintf (info->f, "register ");
180333965Sjdp
1804130561Sobrien  print_vma (val, ab, TRUE, TRUE);
180533965Sjdp  fprintf (info->f, "%s /* %s */", t, ab);
180633965Sjdp
180733965Sjdp  free (t);
180833965Sjdp
180933965Sjdp  ++info->parameter;
181033965Sjdp
1811130561Sobrien  return TRUE;
181233965Sjdp}
181333965Sjdp
181433965Sjdp/* Start writing out a block.  */
181533965Sjdp
1816130561Sobrienstatic bfd_boolean
1817130561Sobrienpr_start_block (void *p, bfd_vma addr)
181833965Sjdp{
181933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
182033965Sjdp  char ab[20];
182133965Sjdp
182233965Sjdp  if (info->parameter > 0)
182333965Sjdp    {
182433965Sjdp      fprintf (info->f, ")\n");
182533965Sjdp      info->parameter = 0;
182633965Sjdp    }
182733965Sjdp
182833965Sjdp  indent (info);
1829130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
183033965Sjdp  fprintf (info->f, "{ /* %s */\n", ab);
183133965Sjdp
183233965Sjdp  info->indent += 2;
183333965Sjdp
1834130561Sobrien  return TRUE;
183533965Sjdp}
183633965Sjdp
183733965Sjdp/* Write out line number information.  */
183833965Sjdp
1839130561Sobrienstatic bfd_boolean
1840130561Sobrienpr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
184133965Sjdp{
184233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
184333965Sjdp  char ab[20];
184433965Sjdp
184533965Sjdp  indent (info);
1846130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
184733965Sjdp  fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
184833965Sjdp
1849130561Sobrien  return TRUE;
185033965Sjdp}
185133965Sjdp
185233965Sjdp/* Finish writing out a block.  */
185333965Sjdp
1854130561Sobrienstatic bfd_boolean
1855130561Sobrienpr_end_block (void *p, bfd_vma addr)
185633965Sjdp{
185733965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
185833965Sjdp  char ab[20];
185933965Sjdp
186033965Sjdp  info->indent -= 2;
186133965Sjdp
186233965Sjdp  indent (info);
1863130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
186433965Sjdp  fprintf (info->f, "} /* %s */\n", ab);
186533965Sjdp
1866130561Sobrien  return TRUE;
186733965Sjdp}
186833965Sjdp
186933965Sjdp/* Finish writing out a function.  */
187033965Sjdp
1871130561Sobrienstatic bfd_boolean
1872130561Sobrienpr_end_function (void *p ATTRIBUTE_UNUSED)
187333965Sjdp{
1874130561Sobrien  return TRUE;
187533965Sjdp}
1876130561Sobrien
1877130561Sobrien/* Tags style generation functions start here.  */
1878130561Sobrien
1879130561Sobrien/* Variables for address to line translation.  */
1880130561Sobrienstatic bfd_vma pc;
1881130561Sobrienstatic const char *filename;
1882130561Sobrienstatic const char *functionname;
1883130561Sobrienstatic unsigned int line;
1884130561Sobrienstatic bfd_boolean found;
1885130561Sobrien
1886130561Sobrien/* Look for an address in a section.  This is called via
1887130561Sobrien   bfd_map_over_sections.  */
1888130561Sobrien
1889130561Sobrienstatic void
1890130561Sobrienfind_address_in_section (bfd *abfd, asection *section, void *data)
1891130561Sobrien{
1892130561Sobrien  bfd_vma vma;
1893130561Sobrien  bfd_size_type size;
1894130561Sobrien  asymbol **syms = (asymbol **) data;
1895130561Sobrien
1896130561Sobrien  if (found)
1897130561Sobrien    return;
1898130561Sobrien
1899130561Sobrien  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
1900130561Sobrien    return;
1901130561Sobrien
1902130561Sobrien  vma = bfd_get_section_vma (abfd, section);
1903130561Sobrien  if (pc < vma)
1904130561Sobrien    return;
1905130561Sobrien
1906218822Sdim  size = bfd_get_section_size (section);
1907130561Sobrien  if (pc >= vma + size)
1908130561Sobrien    return;
1909130561Sobrien
1910130561Sobrien  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
1911130561Sobrien				 &filename, &functionname, &line);
1912130561Sobrien}
1913130561Sobrien
1914130561Sobrienstatic void
1915130561Sobrientranslate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms)
1916130561Sobrien{
1917130561Sobrien  pc = bfd_scan_vma (addr_hex, NULL, 16);
1918130561Sobrien  found = FALSE;
1919130561Sobrien  bfd_map_over_sections (abfd, find_address_in_section, syms);
1920130561Sobrien
1921130561Sobrien  if (! found)
1922130561Sobrien    fprintf (f, "??");
1923130561Sobrien  else
1924130561Sobrien    fprintf (f, "%u", line);
1925130561Sobrien}
1926130561Sobrien
1927130561Sobrien/* Start a new compilation unit.  */
1928130561Sobrien
1929130561Sobrienstatic bfd_boolean
1930130561Sobrientg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED)
1931130561Sobrien{
1932130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1933130561Sobrien
1934130561Sobrien  fprintf (stderr, "New compilation unit: %s\n", filename);
1935130561Sobrien
1936130561Sobrien  free (info->filename);
1937130561Sobrien  /* Should it be relative? best way to do it here?.  */
1938130561Sobrien  info->filename = strdup (filename);
1939130561Sobrien
1940130561Sobrien  return TRUE;
1941130561Sobrien}
1942130561Sobrien
1943130561Sobrien/* Start a source file within a compilation unit.  */
1944130561Sobrien
1945130561Sobrienstatic bfd_boolean
1946130561Sobrientg_start_source (void *p, const char *filename)
1947130561Sobrien{
1948130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1949130561Sobrien
1950130561Sobrien  free (info->filename);
1951130561Sobrien  /* Should it be relative? best way to do it here?.  */
1952130561Sobrien  info->filename = strdup (filename);
1953130561Sobrien
1954130561Sobrien  return TRUE;
1955130561Sobrien}
1956130561Sobrien
1957130561Sobrien/* Push an enum type onto the type stack.  */
1958130561Sobrien
1959130561Sobrienstatic bfd_boolean
1960130561Sobrientg_enum_type (void *p, const char *tag, const char **names,
1961130561Sobrien	      bfd_signed_vma *values)
1962130561Sobrien{
1963130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1964130561Sobrien  unsigned int i;
1965130561Sobrien  const char *name;
1966130561Sobrien  char ab[20];
1967130561Sobrien
1968130561Sobrien  if (! pr_enum_type (p, tag, names, values))
1969130561Sobrien    return FALSE;
1970130561Sobrien
1971130561Sobrien  name = tag ? tag : "unknown";
1972130561Sobrien  /* Generate an entry for the enum.  */
1973130561Sobrien  if (tag)
1974130561Sobrien    fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag,
1975130561Sobrien	     info->filename, info->stack->type);
1976130561Sobrien
1977130561Sobrien  /* Generate entries for the values.  */
1978130561Sobrien  if (names != NULL)
1979130561Sobrien    {
1980130561Sobrien      for (i = 0; names[i] != NULL; i++)
1981130561Sobrien	{
1982130561Sobrien	  print_vma (values[i], ab, FALSE, FALSE);
1983130561Sobrien	  fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n",
1984130561Sobrien		   names[i], info->filename, name, ab);
1985130561Sobrien	}
1986130561Sobrien    }
1987130561Sobrien
1988130561Sobrien  return TRUE;
1989130561Sobrien}
1990130561Sobrien
1991130561Sobrien/* Start accumulating a struct type.  */
1992130561Sobrien
1993130561Sobrienstatic bfd_boolean
1994130561Sobrientg_start_struct_type (void *p, const char *tag, unsigned int id,
1995130561Sobrien		      bfd_boolean structp,
1996130561Sobrien		      unsigned int size ATTRIBUTE_UNUSED)
1997130561Sobrien{
1998130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1999130561Sobrien  const char *name;
2000130561Sobrien  char idbuf[20];
2001130561Sobrien
2002130561Sobrien  if (tag != NULL)
2003130561Sobrien    name = tag;
2004130561Sobrien  else
2005130561Sobrien    {
2006130561Sobrien      name = idbuf;
2007130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2008130561Sobrien    }
2009130561Sobrien
2010130561Sobrien  if (! push_type (info, name))
2011130561Sobrien    return FALSE;
2012130561Sobrien
2013130561Sobrien  info->stack->flavor = structp ? "struct" : "union";
2014130561Sobrien
2015130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename,
2016130561Sobrien	   info->stack->flavor[0]);
2017130561Sobrien
2018130561Sobrien  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
2019130561Sobrien
2020130561Sobrien  return indent_type (info);
2021130561Sobrien}
2022130561Sobrien
2023130561Sobrien/* Output the visibility of a field in a struct.  */
2024130561Sobrien
2025130561Sobrienstatic bfd_boolean
2026130561Sobrientg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
2027130561Sobrien{
2028130561Sobrien  assert (info->stack != NULL);
2029130561Sobrien
2030130561Sobrien  if (info->stack->visibility == visibility)
2031130561Sobrien    return TRUE;
2032130561Sobrien
2033130561Sobrien  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
2034130561Sobrien
2035130561Sobrien  info->stack->visibility = visibility;
2036130561Sobrien
2037130561Sobrien  return TRUE;
2038130561Sobrien}
2039130561Sobrien
2040130561Sobrien/* Add a field to a struct type.  */
2041130561Sobrien
2042130561Sobrienstatic bfd_boolean
2043130561Sobrientg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED,
2044130561Sobrien		 bfd_vma bitsize ATTRIBUTE_UNUSED,
2045130561Sobrien		 enum debug_visibility visibility)
2046130561Sobrien{
2047130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2048130561Sobrien  char *t;
2049130561Sobrien
2050130561Sobrien  t = pop_type (info);
2051130561Sobrien  if (t == NULL)
2052130561Sobrien    return FALSE;
2053130561Sobrien
2054130561Sobrien  if (! tg_fix_visibility (info, visibility))
2055130561Sobrien    return FALSE;
2056130561Sobrien
2057130561Sobrien  /* It happens, a bug? */
2058130561Sobrien  if (! name[0])
2059130561Sobrien    return TRUE;
2060130561Sobrien
2061130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
2062130561Sobrien	   name, info->filename, t, info->stack->flavor, info->stack->type,
2063130561Sobrien	   visibility_name (visibility));
2064130561Sobrien
2065130561Sobrien  return TRUE;
2066130561Sobrien}
2067130561Sobrien
2068130561Sobrien/* Finish a struct type.  */
2069130561Sobrien
2070130561Sobrienstatic bfd_boolean
2071130561Sobrientg_end_struct_type (void *p ATTRIBUTE_UNUSED)
2072130561Sobrien{
2073130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2074130561Sobrien  assert (info->stack != NULL);
2075130561Sobrien
2076130561Sobrien  return TRUE;
2077130561Sobrien}
2078130561Sobrien
2079130561Sobrien/* Start a class type.  */
2080130561Sobrien
2081130561Sobrienstatic bfd_boolean
2082130561Sobrientg_start_class_type (void *p, const char *tag, unsigned int id,
2083130561Sobrien		     bfd_boolean structp, unsigned int size,
2084130561Sobrien		     bfd_boolean vptr, bfd_boolean ownvptr)
2085130561Sobrien{
2086130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2087130561Sobrien  char *tv = NULL;
2088130561Sobrien  const char *name;
2089130561Sobrien
2090130561Sobrien  info->indent += 2;
2091130561Sobrien
2092130561Sobrien  if (vptr && ! ownvptr)
2093130561Sobrien    {
2094130561Sobrien      tv = pop_type (info);
2095130561Sobrien      if (tv == NULL)
2096130561Sobrien	return FALSE;
2097130561Sobrien    }
2098130561Sobrien
2099130561Sobrien  if (tag != NULL)
2100130561Sobrien    name = tag;
2101130561Sobrien  else
2102130561Sobrien    {
2103130561Sobrien      char idbuf[20];
2104130561Sobrien
2105130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2106130561Sobrien      name = idbuf;
2107130561Sobrien    }
2108130561Sobrien
2109130561Sobrien  if (! push_type (info, name))
2110130561Sobrien    return FALSE;
2111130561Sobrien
2112130561Sobrien  info->stack->flavor = structp ? "class" : "union class";
2113130561Sobrien  info->stack->parents = NULL;
2114130561Sobrien  info->stack->num_parents = 0;
2115130561Sobrien
2116130561Sobrien  if (size != 0 || vptr || ownvptr || tag != NULL)
2117130561Sobrien    {
2118130561Sobrien      if (vptr)
2119130561Sobrien	{
2120130561Sobrien	  if (! append_type (info, " vtable "))
2121130561Sobrien	    return FALSE;
2122130561Sobrien	  if (ownvptr)
2123130561Sobrien	    {
2124130561Sobrien	      if (! append_type (info, "self "))
2125130561Sobrien		return FALSE;
2126130561Sobrien	    }
2127130561Sobrien	  else
2128130561Sobrien	    {
2129130561Sobrien	      if (! append_type (info, tv)
2130130561Sobrien		  || ! append_type (info, " "))
2131130561Sobrien		return FALSE;
2132130561Sobrien	    }
2133130561Sobrien	}
2134130561Sobrien    }
2135130561Sobrien
2136130561Sobrien  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
2137130561Sobrien
2138130561Sobrien  return TRUE;
2139130561Sobrien}
2140130561Sobrien
2141130561Sobrien/* Add a static member to a class.  */
2142130561Sobrien
2143130561Sobrienstatic bfd_boolean
2144130561Sobrientg_class_static_member (void *p, const char *name,
2145130561Sobrien			const char *physname ATTRIBUTE_UNUSED,
2146130561Sobrien			enum debug_visibility visibility)
2147130561Sobrien{
2148130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2149130561Sobrien  char *t;
2150130561Sobrien  int len_var, len_class;
2151130561Sobrien  char *full_name;
2152130561Sobrien
2153130561Sobrien  len_var = strlen (name);
2154130561Sobrien  len_class = strlen (info->stack->next->type);
2155218822Sdim  full_name = xmalloc (len_var + len_class + 3);
2156130561Sobrien  if (! full_name)
2157130561Sobrien    return FALSE;
2158218822Sdim  sprintf (full_name, "%s::%s", info->stack->next->type, name);
2159130561Sobrien
2160130561Sobrien  if (! substitute_type (info, full_name))
2161130561Sobrien    return FALSE;
2162130561Sobrien
2163130561Sobrien  if (! prepend_type (info, "static "))
2164130561Sobrien    return FALSE;
2165130561Sobrien
2166130561Sobrien  t = pop_type (info);
2167130561Sobrien  if (t == NULL)
2168130561Sobrien    return FALSE;
2169130561Sobrien
2170130561Sobrien  if (! tg_fix_visibility (info, visibility))
2171130561Sobrien    return FALSE;
2172130561Sobrien
2173130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n",
2174130561Sobrien	   name, info->filename, t, info->stack->type,
2175130561Sobrien	   visibility_name (visibility));
2176130561Sobrien  free (t);
2177130561Sobrien  free (full_name);
2178130561Sobrien
2179130561Sobrien  return TRUE;
2180130561Sobrien}
2181130561Sobrien
2182130561Sobrien/* Add a base class to a class.  */
2183130561Sobrien
2184130561Sobrienstatic bfd_boolean
2185130561Sobrientg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
2186130561Sobrien		    bfd_boolean virtual, enum debug_visibility visibility)
2187130561Sobrien{
2188130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2189130561Sobrien  char *t;
2190130561Sobrien  const char *prefix;
2191130561Sobrien
2192130561Sobrien  assert (info->stack != NULL && info->stack->next != NULL);
2193130561Sobrien
2194130561Sobrien  t = pop_type (info);
2195130561Sobrien  if (t == NULL)
2196130561Sobrien    return FALSE;
2197130561Sobrien
2198218822Sdim  if (CONST_STRNEQ (t, "class "))
2199130561Sobrien    t += sizeof "class " - 1;
2200130561Sobrien
2201130561Sobrien  /* Push it back on to take advantage of the prepend_type and
2202130561Sobrien     append_type routines.  */
2203130561Sobrien  if (! push_type (info, t))
2204130561Sobrien    return FALSE;
2205130561Sobrien
2206130561Sobrien  if (virtual)
2207130561Sobrien    {
2208130561Sobrien      if (! prepend_type (info, "virtual "))
2209130561Sobrien	return FALSE;
2210130561Sobrien    }
2211130561Sobrien
2212130561Sobrien  switch (visibility)
2213130561Sobrien    {
2214130561Sobrien    case DEBUG_VISIBILITY_PUBLIC:
2215130561Sobrien      prefix = "public ";
2216130561Sobrien      break;
2217130561Sobrien    case DEBUG_VISIBILITY_PROTECTED:
2218130561Sobrien      prefix = "protected ";
2219130561Sobrien      break;
2220130561Sobrien    case DEBUG_VISIBILITY_PRIVATE:
2221130561Sobrien      prefix = "private ";
2222130561Sobrien      break;
2223130561Sobrien    default:
2224130561Sobrien      prefix = "/* unknown visibility */ ";
2225130561Sobrien      break;
2226130561Sobrien    }
2227130561Sobrien
2228130561Sobrien  if (! prepend_type (info, prefix))
2229130561Sobrien    return FALSE;
2230130561Sobrien
2231130561Sobrien  t = pop_type (info);
2232130561Sobrien  if (t == NULL)
2233130561Sobrien    return FALSE;
2234130561Sobrien
2235130561Sobrien  if (info->stack->num_parents && ! append_parent (info, ", "))
2236130561Sobrien    return FALSE;
2237130561Sobrien
2238130561Sobrien  if (! append_parent (info, t))
2239130561Sobrien    return FALSE;
2240130561Sobrien  info->stack->num_parents++;
2241130561Sobrien
2242130561Sobrien  free (t);
2243130561Sobrien
2244130561Sobrien  return TRUE;
2245130561Sobrien}
2246130561Sobrien
2247130561Sobrien/* Add a variant to a method.  */
2248130561Sobrien
2249130561Sobrienstatic bfd_boolean
2250130561Sobrientg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED,
2251130561Sobrien			 enum debug_visibility visibility,
2252130561Sobrien			 bfd_boolean constp, bfd_boolean volatilep,
2253130561Sobrien			 bfd_vma voffset ATTRIBUTE_UNUSED,
2254130561Sobrien			 bfd_boolean context)
2255130561Sobrien{
2256130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2257130561Sobrien  char *method_type;
2258130561Sobrien  char *context_type;
2259130561Sobrien  char *method_name;
2260130561Sobrien
2261130561Sobrien  assert (info->stack != NULL);
2262130561Sobrien  assert (info->stack->next != NULL);
2263130561Sobrien
2264130561Sobrien  /* Put the const and volatile qualifiers on the type.  */
2265130561Sobrien  if (volatilep)
2266130561Sobrien    {
2267130561Sobrien      if (! append_type (info, " volatile"))
2268130561Sobrien	return FALSE;
2269130561Sobrien    }
2270130561Sobrien  if (constp)
2271130561Sobrien    {
2272130561Sobrien      if (! append_type (info, " const"))
2273130561Sobrien	return FALSE;
2274130561Sobrien    }
2275130561Sobrien
2276130561Sobrien  method_name = strdup (context ? info->stack->next->next->method
2277130561Sobrien			: info->stack->next->method);
2278130561Sobrien
2279130561Sobrien  /* Stick the name of the method into its type.  */
2280130561Sobrien  if (! substitute_type (info, method_name))
2281130561Sobrien    return FALSE;
2282130561Sobrien
2283130561Sobrien  /* Get the type.  */
2284130561Sobrien  method_type = pop_type (info);
2285130561Sobrien  if (method_type == NULL)
2286130561Sobrien    return FALSE;
2287130561Sobrien
2288130561Sobrien  /* Pull off the context type if there is one.  */
2289130561Sobrien  if (! context)
2290130561Sobrien    context_type = NULL;
2291130561Sobrien  else
2292130561Sobrien    {
2293130561Sobrien      context_type = pop_type (info);
2294130561Sobrien      if (context_type == NULL)
2295130561Sobrien	return FALSE;
2296130561Sobrien    }
2297130561Sobrien
2298130561Sobrien  /* Now the top of the stack is the class.  */
2299130561Sobrien  if (! tg_fix_visibility (info, visibility))
2300130561Sobrien    return FALSE;
2301130561Sobrien
2302130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n",
2303130561Sobrien	   method_name, info->filename, method_type, info->stack->type);
2304130561Sobrien  free (method_type);
2305130561Sobrien  free (method_name);
2306130561Sobrien  free (context_type);
2307130561Sobrien
2308130561Sobrien  return TRUE;
2309130561Sobrien}
2310130561Sobrien
2311130561Sobrien/* Add a static variant to a method.  */
2312130561Sobrien
2313130561Sobrienstatic bfd_boolean
2314130561Sobrientg_class_static_method_variant (void *p,
2315130561Sobrien				const char *physname ATTRIBUTE_UNUSED,
2316130561Sobrien				enum debug_visibility visibility,
2317130561Sobrien				bfd_boolean constp, bfd_boolean volatilep)
2318130561Sobrien{
2319130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2320130561Sobrien  char *method_type;
2321130561Sobrien  char *method_name;
2322130561Sobrien
2323130561Sobrien  assert (info->stack != NULL);
2324130561Sobrien  assert (info->stack->next != NULL);
2325130561Sobrien  assert (info->stack->next->method != NULL);
2326130561Sobrien
2327130561Sobrien  /* Put the const and volatile qualifiers on the type.  */
2328130561Sobrien  if (volatilep)
2329130561Sobrien    {
2330130561Sobrien      if (! append_type (info, " volatile"))
2331130561Sobrien	return FALSE;
2332130561Sobrien    }
2333130561Sobrien  if (constp)
2334130561Sobrien    {
2335130561Sobrien      if (! append_type (info, " const"))
2336130561Sobrien	return FALSE;
2337130561Sobrien    }
2338130561Sobrien
2339130561Sobrien  /* Mark it as static.  */
2340130561Sobrien  if (! prepend_type (info, "static "))
2341130561Sobrien    return FALSE;
2342130561Sobrien
2343130561Sobrien  method_name = strdup (info->stack->next->method);
2344130561Sobrien  /* Stick the name of the method into its type.  */
2345130561Sobrien  if (! substitute_type (info, info->stack->next->method))
2346130561Sobrien    return FALSE;
2347130561Sobrien
2348130561Sobrien  /* Get the type.  */
2349130561Sobrien  method_type = pop_type (info);
2350130561Sobrien  if (method_type == NULL)
2351130561Sobrien    return FALSE;
2352130561Sobrien
2353130561Sobrien  /* Now the top of the stack is the class.  */
2354130561Sobrien  if (! tg_fix_visibility (info, visibility))
2355130561Sobrien    return FALSE;
2356130561Sobrien
2357130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n",
2358130561Sobrien	   method_name, info->filename, method_type, info->stack->type,
2359130561Sobrien	   visibility_name (visibility));
2360130561Sobrien  free (method_type);
2361130561Sobrien  free (method_name);
2362130561Sobrien
2363130561Sobrien  return TRUE;
2364130561Sobrien}
2365130561Sobrien
2366130561Sobrien/* Finish up a class.  */
2367130561Sobrien
2368130561Sobrienstatic bfd_boolean
2369130561Sobrientg_end_class_type (void *p)
2370130561Sobrien{
2371130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2372130561Sobrien
2373130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type,
2374130561Sobrien	   info->filename, info->stack->flavor);
2375130561Sobrien  if (info->stack->num_parents)
2376130561Sobrien    {
2377130561Sobrien      fprintf  (info->f, "\tinherits:%s", info->stack->parents);
2378130561Sobrien      free (info->stack->parents);
2379130561Sobrien    }
2380130561Sobrien  fputc ('\n', info->f);
2381130561Sobrien
2382130561Sobrien  return tg_end_struct_type (p);
2383130561Sobrien}
2384130561Sobrien
2385130561Sobrien/* Push a type on the stack using a tag name.  */
2386130561Sobrien
2387130561Sobrienstatic bfd_boolean
2388130561Sobrientg_tag_type (void *p, const char *name, unsigned int id,
2389130561Sobrien	     enum debug_type_kind kind)
2390130561Sobrien{
2391130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2392130561Sobrien  const char *t, *tag;
2393130561Sobrien  char idbuf[20];
2394130561Sobrien
2395130561Sobrien  switch (kind)
2396130561Sobrien    {
2397130561Sobrien    case DEBUG_KIND_STRUCT:
2398130561Sobrien      t = "struct ";
2399130561Sobrien      break;
2400130561Sobrien    case DEBUG_KIND_UNION:
2401130561Sobrien      t = "union ";
2402130561Sobrien      break;
2403130561Sobrien    case DEBUG_KIND_ENUM:
2404130561Sobrien      t = "enum ";
2405130561Sobrien      break;
2406130561Sobrien    case DEBUG_KIND_CLASS:
2407130561Sobrien      t = "class ";
2408130561Sobrien      break;
2409130561Sobrien    case DEBUG_KIND_UNION_CLASS:
2410130561Sobrien      t = "union class ";
2411130561Sobrien      break;
2412130561Sobrien    default:
2413130561Sobrien      abort ();
2414130561Sobrien      return FALSE;
2415130561Sobrien    }
2416130561Sobrien
2417130561Sobrien  if (! push_type (info, t))
2418130561Sobrien    return FALSE;
2419130561Sobrien  if (name != NULL)
2420130561Sobrien    tag = name;
2421130561Sobrien  else
2422130561Sobrien    {
2423130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2424130561Sobrien      tag = idbuf;
2425130561Sobrien    }
2426130561Sobrien
2427130561Sobrien  if (! append_type (info, tag))
2428130561Sobrien    return FALSE;
2429130561Sobrien
2430130561Sobrien  return TRUE;
2431130561Sobrien}
2432130561Sobrien
2433130561Sobrien/* Output a typedef.  */
2434130561Sobrien
2435130561Sobrienstatic bfd_boolean
2436130561Sobrientg_typdef (void *p, const char *name)
2437130561Sobrien{
2438130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2439130561Sobrien  char *s;
2440130561Sobrien
2441130561Sobrien  s = pop_type (info);
2442130561Sobrien  if (s == NULL)
2443130561Sobrien    return FALSE;
2444130561Sobrien
2445130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name,
2446130561Sobrien	   info->filename, s);
2447130561Sobrien
2448130561Sobrien  free (s);
2449130561Sobrien
2450130561Sobrien  return TRUE;
2451130561Sobrien}
2452130561Sobrien
2453130561Sobrien/* Output a tag.  The tag should already be in the string on the
2454130561Sobrien   stack, so all we have to do here is print it out.  */
2455130561Sobrien
2456130561Sobrienstatic bfd_boolean
2457130561Sobrientg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED)
2458130561Sobrien{
2459130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2460130561Sobrien  char *t;
2461130561Sobrien
2462130561Sobrien  t = pop_type (info);
2463130561Sobrien  if (t == NULL)
2464130561Sobrien    return FALSE;
2465130561Sobrien  free (t);
2466130561Sobrien
2467130561Sobrien  return TRUE;
2468130561Sobrien}
2469130561Sobrien
2470130561Sobrien/* Output an integer constant.  */
2471130561Sobrien
2472130561Sobrienstatic bfd_boolean
2473130561Sobrientg_int_constant (void *p, const char *name, bfd_vma val)
2474130561Sobrien{
2475130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2476130561Sobrien  char ab[20];
2477130561Sobrien
2478130561Sobrien  indent (info);
2479130561Sobrien  print_vma (val, ab, FALSE, FALSE);
2480130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n",
2481130561Sobrien	   name, info->filename, ab);
2482130561Sobrien  return TRUE;
2483130561Sobrien}
2484130561Sobrien
2485130561Sobrien/* Output a floating point constant.  */
2486130561Sobrien
2487130561Sobrienstatic bfd_boolean
2488130561Sobrientg_float_constant (void *p, const char *name, double val)
2489130561Sobrien{
2490130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2491130561Sobrien
2492130561Sobrien  indent (info);
2493130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n",
2494130561Sobrien	   name, info->filename, val);
2495130561Sobrien  return TRUE;
2496130561Sobrien}
2497130561Sobrien
2498130561Sobrien/* Output a typed constant.  */
2499130561Sobrien
2500130561Sobrienstatic bfd_boolean
2501130561Sobrientg_typed_constant (void *p, const char *name, bfd_vma val)
2502130561Sobrien{
2503130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2504130561Sobrien  char *t;
2505130561Sobrien  char ab[20];
2506130561Sobrien
2507130561Sobrien  t = pop_type (info);
2508130561Sobrien  if (t == NULL)
2509130561Sobrien    return FALSE;
2510130561Sobrien
2511130561Sobrien  indent (info);
2512130561Sobrien  print_vma (val, ab, FALSE, FALSE);
2513130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n",
2514130561Sobrien	   name, info->filename, t, ab);
2515130561Sobrien
2516130561Sobrien  free (t);
2517130561Sobrien
2518130561Sobrien  return TRUE;
2519130561Sobrien}
2520130561Sobrien
2521130561Sobrien/* Output a variable.  */
2522130561Sobrien
2523130561Sobrienstatic bfd_boolean
2524130561Sobrientg_variable (void *p, const char *name, enum debug_var_kind kind,
2525130561Sobrien	     bfd_vma val ATTRIBUTE_UNUSED)
2526130561Sobrien{
2527130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2528218822Sdim  char *t, *dname, *from_class;
2529130561Sobrien
2530130561Sobrien  t = pop_type (info);
2531130561Sobrien  if (t == NULL)
2532130561Sobrien    return FALSE;
2533130561Sobrien
2534218822Sdim  dname = NULL;
2535130561Sobrien  if (info->demangler)
2536218822Sdim    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
2537130561Sobrien
2538218822Sdim  from_class = NULL;
2539218822Sdim  if (dname != NULL)
2540130561Sobrien    {
2541130561Sobrien      char *sep;
2542130561Sobrien      sep = strstr (dname, "::");
2543130561Sobrien      if (sep)
2544130561Sobrien	{
2545130561Sobrien	  *sep = 0;
2546130561Sobrien	  name = sep + 2;
2547130561Sobrien	  from_class = dname;
2548130561Sobrien	}
2549130561Sobrien      else
2550218822Sdim	/* Obscure types as vts and type_info nodes.  */
2551218822Sdim	name = dname;
2552130561Sobrien    }
2553130561Sobrien
2554130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t);
2555130561Sobrien
2556130561Sobrien  switch (kind)
2557130561Sobrien    {
2558130561Sobrien    case DEBUG_STATIC:
2559130561Sobrien    case DEBUG_LOCAL_STATIC:
2560130561Sobrien      fprintf (info->f, "\tfile:");
2561130561Sobrien      break;
2562130561Sobrien    case DEBUG_REGISTER:
2563130561Sobrien      fprintf (info->f, "\tregister:");
2564130561Sobrien      break;
2565130561Sobrien    default:
2566130561Sobrien      break;
2567130561Sobrien    }
2568130561Sobrien
2569130561Sobrien  if (from_class)
2570218822Sdim    fprintf (info->f, "\tclass:%s", from_class);
2571130561Sobrien
2572218822Sdim  if (dname)
2573218822Sdim    free (dname);
2574218822Sdim
2575130561Sobrien  fprintf (info->f, "\n");
2576130561Sobrien
2577130561Sobrien  free (t);
2578130561Sobrien
2579130561Sobrien  return TRUE;
2580130561Sobrien}
2581130561Sobrien
2582130561Sobrien/* Start outputting a function.  */
2583130561Sobrien
2584130561Sobrienstatic bfd_boolean
2585130561Sobrientg_start_function (void *p, const char *name, bfd_boolean global)
2586130561Sobrien{
2587130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2588218822Sdim  char *dname;
2589130561Sobrien
2590130561Sobrien  if (! global)
2591130561Sobrien    info->stack->flavor = "static";
2592130561Sobrien  else
2593130561Sobrien    info->stack->flavor = NULL;
2594130561Sobrien
2595218822Sdim  dname = NULL;
2596130561Sobrien  if (info->demangler)
2597218822Sdim    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
2598130561Sobrien
2599218822Sdim  if (! substitute_type (info, dname ? dname : name))
2600130561Sobrien    return FALSE;
2601130561Sobrien
2602218822Sdim  info->stack->method = NULL;
2603218822Sdim  if (dname != NULL)
2604130561Sobrien    {
2605130561Sobrien      char *sep;
2606130561Sobrien      sep = strstr (dname, "::");
2607130561Sobrien      if (sep)
2608130561Sobrien	{
2609130561Sobrien	  info->stack->method = dname;
2610130561Sobrien	  *sep = 0;
2611130561Sobrien	  name = sep + 2;
2612130561Sobrien	}
2613130561Sobrien      else
2614130561Sobrien	{
2615130561Sobrien	  info->stack->method = "";
2616130561Sobrien	  name = dname;
2617130561Sobrien	}
2618130561Sobrien      sep = strchr (name, '(');
2619130561Sobrien      if (sep)
2620130561Sobrien	*sep = 0;
2621130561Sobrien      /* Obscure functions as type_info function.  */
2622130561Sobrien    }
2623130561Sobrien
2624130561Sobrien  info->stack->parents = strdup (name);
2625130561Sobrien
2626130561Sobrien  if (! info->stack->method && ! append_type (info, "("))
2627130561Sobrien    return FALSE;
2628130561Sobrien
2629130561Sobrien  info->parameter = 1;
2630130561Sobrien
2631130561Sobrien  return TRUE;
2632130561Sobrien}
2633130561Sobrien
2634130561Sobrien/* Output a function parameter.  */
2635130561Sobrien
2636130561Sobrienstatic bfd_boolean
2637130561Sobrientg_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
2638130561Sobrien		       bfd_vma val ATTRIBUTE_UNUSED)
2639130561Sobrien{
2640130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2641130561Sobrien  char *t;
2642130561Sobrien
2643130561Sobrien  if (kind == DEBUG_PARM_REFERENCE
2644130561Sobrien      || kind == DEBUG_PARM_REF_REG)
2645130561Sobrien    {
2646130561Sobrien      if (! pr_reference_type (p))
2647130561Sobrien	return FALSE;
2648130561Sobrien    }
2649130561Sobrien
2650130561Sobrien  if (! substitute_type (info, name))
2651130561Sobrien    return FALSE;
2652130561Sobrien
2653130561Sobrien  t = pop_type (info);
2654130561Sobrien  if (t == NULL)
2655130561Sobrien    return FALSE;
2656130561Sobrien
2657130561Sobrien  if (! info->stack->method)
2658130561Sobrien    {
2659130561Sobrien      if (info->parameter != 1 && ! append_type (info, ", "))
2660130561Sobrien	return FALSE;
2661130561Sobrien
2662130561Sobrien      if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
2663130561Sobrien	if (! append_type (info, "register "))
2664130561Sobrien	  return FALSE;
2665130561Sobrien
2666130561Sobrien      if (! append_type (info, t))
2667130561Sobrien	return FALSE;
2668130561Sobrien    }
2669130561Sobrien
2670130561Sobrien  free (t);
2671130561Sobrien
2672130561Sobrien  ++info->parameter;
2673130561Sobrien
2674130561Sobrien  return TRUE;
2675130561Sobrien}
2676130561Sobrien
2677130561Sobrien/* Start writing out a block.  */
2678130561Sobrien
2679130561Sobrienstatic bfd_boolean
2680130561Sobrientg_start_block (void *p, bfd_vma addr)
2681130561Sobrien{
2682130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2683130561Sobrien  char ab[20], kind, *partof;
2684130561Sobrien  char *t;
2685130561Sobrien  bfd_boolean local;
2686130561Sobrien
2687130561Sobrien  if (info->parameter > 0)
2688130561Sobrien    {
2689130561Sobrien      info->parameter = 0;
2690130561Sobrien
2691130561Sobrien      /* Delayed name.  */
2692130561Sobrien      fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
2693130561Sobrien      free (info->stack->parents);
2694130561Sobrien
2695130561Sobrien      print_vma (addr, ab, TRUE, TRUE);
2696130561Sobrien      translate_addresses (info->abfd, ab, info->f, info->syms);
2697130561Sobrien      local = info->stack->flavor != NULL;
2698130561Sobrien      if (info->stack->method && *info->stack->method)
2699130561Sobrien	{
2700130561Sobrien	  kind = 'm';
2701130561Sobrien	  partof = (char *) info->stack->method;
2702130561Sobrien	}
2703130561Sobrien      else
2704130561Sobrien	{
2705130561Sobrien	  kind = 'f';
2706130561Sobrien	  partof = NULL;
2707130561Sobrien	  if (! info->stack->method && ! append_type (info, ")"))
2708130561Sobrien	    return FALSE;
2709130561Sobrien	}
2710130561Sobrien      t = pop_type (info);
2711130561Sobrien      if (t == NULL)
2712130561Sobrien	return FALSE;
2713130561Sobrien      fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t);
2714130561Sobrien      if (local)
2715130561Sobrien	fputs ("\tfile:", info->f);
2716130561Sobrien      if (partof)
2717130561Sobrien	{
2718130561Sobrien	  fprintf (info->f, "\tclass:%s", partof);
2719130561Sobrien	  free (partof);
2720130561Sobrien	}
2721130561Sobrien      fputc ('\n', info->f);
2722130561Sobrien    }
2723130561Sobrien
2724130561Sobrien  return TRUE;
2725130561Sobrien}
2726130561Sobrien
2727130561Sobrien/* Write out line number information.  */
2728130561Sobrien
2729130561Sobrienstatic bfd_boolean
2730130561Sobrientg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED,
2731130561Sobrien	   unsigned long lineno ATTRIBUTE_UNUSED,
2732130561Sobrien	   bfd_vma addr ATTRIBUTE_UNUSED)
2733130561Sobrien{
2734130561Sobrien  return TRUE;
2735130561Sobrien}
2736130561Sobrien
2737130561Sobrien/* Finish writing out a block.  */
2738130561Sobrien
2739130561Sobrienstatic bfd_boolean
2740130561Sobrientg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED)
2741130561Sobrien{
2742130561Sobrien  return TRUE;
2743130561Sobrien}
2744130561Sobrien
2745130561Sobrien/* Convert the visibility value into a human readable name.  */
2746130561Sobrien
2747130561Sobrienstatic const char *
2748130561Sobrienvisibility_name (enum debug_visibility visibility)
2749130561Sobrien{
2750130561Sobrien  const char *s;
2751130561Sobrien
2752130561Sobrien  switch (visibility)
2753130561Sobrien    {
2754130561Sobrien    case DEBUG_VISIBILITY_PUBLIC:
2755130561Sobrien      s = "public";
2756130561Sobrien      break;
2757130561Sobrien    case DEBUG_VISIBILITY_PRIVATE:
2758130561Sobrien      s = "private";
2759130561Sobrien      break;
2760130561Sobrien    case DEBUG_VISIBILITY_PROTECTED:
2761130561Sobrien      s = "protected";
2762130561Sobrien      break;
2763130561Sobrien    case DEBUG_VISIBILITY_IGNORE:
2764130561Sobrien      s = "/* ignore */";
2765130561Sobrien      break;
2766130561Sobrien    default:
2767130561Sobrien      abort ();
2768130561Sobrien      return FALSE;
2769130561Sobrien    }
2770130561Sobrien  return s;
2771130561Sobrien}
2772