prdbg.c revision 130561
133965Sjdp/* prdbg.c -- Print out generic debugging information.
2130561Sobrien   Copyright 1995, 1996, 2002, 2003 Free Software Foundation, Inc.
333965Sjdp   Written by Ian Lance Taylor <ian@cygnus.com>.
4130561Sobrien   Tags style generation written by Salvador E. Tropea <set@computer.org>.
533965Sjdp
633965Sjdp   This file is part of GNU Binutils.
733965Sjdp
833965Sjdp   This program is free software; you can redistribute it and/or modify
933965Sjdp   it under the terms of the GNU General Public License as published by
1033965Sjdp   the Free Software Foundation; either version 2 of the License, or
1133965Sjdp   (at your option) any later version.
1233965Sjdp
1333965Sjdp   This program is distributed in the hope that it will be useful,
1433965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1533965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965Sjdp   GNU General Public License for more details.
1733965Sjdp
1833965Sjdp   You should have received a copy of the GNU General Public License
1933965Sjdp   along with this program; if not, write to the Free Software
2033965Sjdp   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
2133965Sjdp   02111-1307, USA.  */
2233965Sjdp
2333965Sjdp/* This file prints out the generic debugging information, by
2433965Sjdp   supplying a set of routines to debug_write.  */
2533965Sjdp
2633965Sjdp#include <stdio.h>
2733965Sjdp#include <assert.h>
2833965Sjdp
2933965Sjdp#include "bfd.h"
3033965Sjdp#include "bucomm.h"
3133965Sjdp#include "libiberty.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.  */
55130561Sobrien  char *(*demangler) (bfd *, const char *);
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
72633965Sjdp  s = (char *) xmalloc (len);
72733965Sjdp  strcpy (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;
91233965Sjdp      if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0
91333965Sjdp	  && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
91433965Sjdp	domain_type += sizeof "class " - 1;
91533965Sjdp      else if (strncmp (domain_type, "union class ",
91633965Sjdp			sizeof "union class ") == 0
91733965Sjdp	       && (strchr (domain_type + sizeof "union class " - 1, ' ')
91833965Sjdp		   == NULL))
91933965Sjdp	domain_type += sizeof "union class " - 1;
92033965Sjdp      len += strlen (domain_type);
92133965Sjdp    }
92233965Sjdp
92333965Sjdp  if (argcount <= 0)
92433965Sjdp    {
92533965Sjdp      arg_types = NULL;
92633965Sjdp      len += 15;
92733965Sjdp    }
92833965Sjdp  else
92933965Sjdp    {
93033965Sjdp      int i;
93133965Sjdp
93233965Sjdp      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
93333965Sjdp      for (i = argcount - 1; i >= 0; i--)
93433965Sjdp	{
93533965Sjdp	  if (! substitute_type (info, ""))
936130561Sobrien	    return FALSE;
93733965Sjdp	  arg_types[i] = pop_type (info);
93833965Sjdp	  if (arg_types[i] == NULL)
939130561Sobrien	    return FALSE;
94033965Sjdp	  len += strlen (arg_types[i]) + 2;
94133965Sjdp	}
94233965Sjdp      if (varargs)
94333965Sjdp	len += 5;
94433965Sjdp    }
94533965Sjdp
94633965Sjdp  /* Now the return type is on the top of the stack.  */
94733965Sjdp
94833965Sjdp  s = (char *) xmalloc (len);
94933965Sjdp  if (! domain)
95033965Sjdp    *s = '\0';
95133965Sjdp  else
95233965Sjdp    strcpy (s, domain_type);
95333965Sjdp  strcat (s, "::| (");
95433965Sjdp
95533965Sjdp  if (argcount < 0)
95633965Sjdp    strcat (s, "/* unknown */");
95733965Sjdp  else
95833965Sjdp    {
95933965Sjdp      int i;
96033965Sjdp
96133965Sjdp      for (i = 0; i < argcount; i++)
96233965Sjdp	{
96333965Sjdp	  if (i > 0)
96433965Sjdp	    strcat (s, ", ");
96533965Sjdp	  strcat (s, arg_types[i]);
96633965Sjdp	}
96733965Sjdp      if (varargs)
96833965Sjdp	{
96933965Sjdp	  if (i > 0)
97033965Sjdp	    strcat (s, ", ");
97133965Sjdp	  strcat (s, "...");
97233965Sjdp	}
97333965Sjdp      if (argcount > 0)
97433965Sjdp	free (arg_types);
97533965Sjdp    }
97633965Sjdp
97733965Sjdp  strcat (s, ")");
97833965Sjdp
97933965Sjdp  if (! substitute_type (info, s))
980130561Sobrien    return FALSE;
98133965Sjdp
98233965Sjdp  free (s);
98333965Sjdp
984130561Sobrien  return TRUE;
98533965Sjdp}
98633965Sjdp
98733965Sjdp/* Make a const qualified type.  */
98833965Sjdp
989130561Sobrienstatic bfd_boolean
990130561Sobrienpr_const_type (void *p)
99133965Sjdp{
99233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
99333965Sjdp
99433965Sjdp  return substitute_type (info, "const |");
99533965Sjdp}
99633965Sjdp
99733965Sjdp/* Make a volatile qualified type.  */
99833965Sjdp
999130561Sobrienstatic bfd_boolean
1000130561Sobrienpr_volatile_type (void *p)
100133965Sjdp{
100233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
100333965Sjdp
100433965Sjdp  return substitute_type (info, "volatile |");
100533965Sjdp}
100633965Sjdp
100733965Sjdp/* Start accumulating a struct type.  */
100833965Sjdp
1009130561Sobrienstatic bfd_boolean
1010130561Sobrienpr_start_struct_type (void *p, const char *tag, unsigned int id,
1011130561Sobrien		      bfd_boolean structp, unsigned int size)
101233965Sjdp{
101333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
101433965Sjdp
101533965Sjdp  info->indent += 2;
101633965Sjdp
101733965Sjdp  if (! push_type (info, structp ? "struct " : "union "))
1018130561Sobrien    return FALSE;
101933965Sjdp  if (tag != NULL)
102033965Sjdp    {
102133965Sjdp      if (! append_type (info, tag))
1022130561Sobrien	return FALSE;
102333965Sjdp    }
102433965Sjdp  else
102533965Sjdp    {
102633965Sjdp      char idbuf[20];
102733965Sjdp
102833965Sjdp      sprintf (idbuf, "%%anon%u", id);
102933965Sjdp      if (! append_type (info, idbuf))
1030130561Sobrien	return FALSE;
103133965Sjdp    }
103233965Sjdp
103333965Sjdp  if (! append_type (info, " {"))
1034130561Sobrien    return FALSE;
103533965Sjdp  if (size != 0 || tag != NULL)
103633965Sjdp    {
103733965Sjdp      char ab[30];
103833965Sjdp
103933965Sjdp      if (! append_type (info, " /*"))
1040130561Sobrien	return FALSE;
104133965Sjdp
104233965Sjdp      if (size != 0)
104333965Sjdp	{
104433965Sjdp	  sprintf (ab, " size %u", size);
104533965Sjdp	  if (! append_type (info, ab))
1046130561Sobrien	    return FALSE;
104733965Sjdp	}
104833965Sjdp      if (tag != NULL)
104933965Sjdp	{
105033965Sjdp	  sprintf (ab, " id %u", id);
105133965Sjdp	  if (! append_type (info, ab))
1052130561Sobrien	    return FALSE;
105333965Sjdp	}
105433965Sjdp      if (! append_type (info, " */"))
1055130561Sobrien	return FALSE;
105633965Sjdp    }
105733965Sjdp  if (! append_type (info, "\n"))
1058130561Sobrien    return FALSE;
105933965Sjdp
106033965Sjdp  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
106133965Sjdp
106233965Sjdp  return indent_type (info);
106333965Sjdp}
106433965Sjdp
106533965Sjdp/* Output the visibility of a field in a struct.  */
106633965Sjdp
1067130561Sobrienstatic bfd_boolean
1068130561Sobrienpr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
106933965Sjdp{
107060484Sobrien  const char *s = NULL;
107133965Sjdp  char *t;
107233965Sjdp  unsigned int len;
107333965Sjdp
107433965Sjdp  assert (info->stack != NULL);
107533965Sjdp
107633965Sjdp  if (info->stack->visibility == visibility)
1077130561Sobrien    return TRUE;
107833965Sjdp
107933965Sjdp  switch (visibility)
108033965Sjdp    {
108133965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
108233965Sjdp      s = "public";
108333965Sjdp      break;
108433965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
108533965Sjdp      s = "private";
108633965Sjdp      break;
108733965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
108833965Sjdp      s = "protected";
108933965Sjdp      break;
109033965Sjdp    case DEBUG_VISIBILITY_IGNORE:
109133965Sjdp      s = "/* ignore */";
109233965Sjdp      break;
109333965Sjdp    default:
109433965Sjdp      abort ();
1095130561Sobrien      return FALSE;
109633965Sjdp    }
109733965Sjdp
109833965Sjdp  /* Trim off a trailing space in the struct string, to make the
109933965Sjdp     output look a bit better, then stick on the visibility string.  */
110033965Sjdp
110133965Sjdp  t = info->stack->type;
110233965Sjdp  len = strlen (t);
110333965Sjdp  assert (t[len - 1] == ' ');
110433965Sjdp  t[len - 1] = '\0';
110533965Sjdp
110633965Sjdp  if (! append_type (info, s)
110733965Sjdp      || ! append_type (info, ":\n")
110833965Sjdp      || ! indent_type (info))
1109130561Sobrien    return FALSE;
111033965Sjdp
111133965Sjdp  info->stack->visibility = visibility;
111233965Sjdp
1113130561Sobrien  return TRUE;
111433965Sjdp}
111533965Sjdp
111633965Sjdp/* Add a field to a struct type.  */
111733965Sjdp
1118130561Sobrienstatic bfd_boolean
1119130561Sobrienpr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
1120130561Sobrien		 enum debug_visibility visibility)
112133965Sjdp{
112233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
112333965Sjdp  char ab[20];
112433965Sjdp  char *t;
112533965Sjdp
112633965Sjdp  if (! substitute_type (info, name))
1127130561Sobrien    return FALSE;
112833965Sjdp
112933965Sjdp  if (! append_type (info, "; /* "))
1130130561Sobrien    return FALSE;
113133965Sjdp
113233965Sjdp  if (bitsize != 0)
113333965Sjdp    {
1134130561Sobrien      print_vma (bitsize, ab, TRUE, FALSE);
113533965Sjdp      if (! append_type (info, "bitsize ")
113633965Sjdp	  || ! append_type (info, ab)
113733965Sjdp	  || ! append_type (info, ", "))
1138130561Sobrien	return FALSE;
113933965Sjdp    }
114033965Sjdp
1141130561Sobrien  print_vma (bitpos, ab, TRUE, FALSE);
114233965Sjdp  if (! append_type (info, "bitpos ")
114333965Sjdp      || ! append_type (info, ab)
114433965Sjdp      || ! append_type (info, " */\n")
114533965Sjdp      || ! indent_type (info))
1146130561Sobrien    return FALSE;
114733965Sjdp
114833965Sjdp  t = pop_type (info);
114933965Sjdp  if (t == NULL)
1150130561Sobrien    return FALSE;
115133965Sjdp
115233965Sjdp  if (! pr_fix_visibility (info, visibility))
1153130561Sobrien    return FALSE;
115433965Sjdp
115533965Sjdp  return append_type (info, t);
115633965Sjdp}
115733965Sjdp
115833965Sjdp/* Finish a struct type.  */
115933965Sjdp
1160130561Sobrienstatic bfd_boolean
1161130561Sobrienpr_end_struct_type (void *p)
116233965Sjdp{
116333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
116433965Sjdp  char *s;
116533965Sjdp
116633965Sjdp  assert (info->stack != NULL);
116733965Sjdp  assert (info->indent >= 2);
116833965Sjdp
116933965Sjdp  info->indent -= 2;
117033965Sjdp
117133965Sjdp  /* Change the trailing indentation to have a close brace.  */
117233965Sjdp  s = info->stack->type + strlen (info->stack->type) - 2;
117333965Sjdp  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
117433965Sjdp
117533965Sjdp  *s++ = '}';
117633965Sjdp  *s = '\0';
117733965Sjdp
1178130561Sobrien  return TRUE;
117933965Sjdp}
118033965Sjdp
118133965Sjdp/* Start a class type.  */
118233965Sjdp
1183130561Sobrienstatic bfd_boolean
1184130561Sobrienpr_start_class_type (void *p, const char *tag, unsigned int id,
1185130561Sobrien		     bfd_boolean structp, unsigned int size,
1186130561Sobrien		     bfd_boolean vptr, bfd_boolean ownvptr)
118733965Sjdp{
118833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
118933965Sjdp  char *tv = NULL;
119033965Sjdp
119133965Sjdp  info->indent += 2;
119233965Sjdp
119333965Sjdp  if (vptr && ! ownvptr)
119433965Sjdp    {
119533965Sjdp      tv = pop_type (info);
119633965Sjdp      if (tv == NULL)
1197130561Sobrien	return FALSE;
119833965Sjdp    }
119933965Sjdp
120033965Sjdp  if (! push_type (info, structp ? "class " : "union class "))
1201130561Sobrien    return FALSE;
120233965Sjdp  if (tag != NULL)
120333965Sjdp    {
120433965Sjdp      if (! append_type (info, tag))
1205130561Sobrien	return FALSE;
120633965Sjdp    }
120733965Sjdp  else
120833965Sjdp    {
120933965Sjdp      char idbuf[20];
121033965Sjdp
121133965Sjdp      sprintf (idbuf, "%%anon%u", id);
121233965Sjdp      if (! append_type (info, idbuf))
1213130561Sobrien	return FALSE;
121433965Sjdp    }
121533965Sjdp
121633965Sjdp  if (! append_type (info, " {"))
1217130561Sobrien    return FALSE;
121833965Sjdp  if (size != 0 || vptr || ownvptr || tag != NULL)
121933965Sjdp    {
122033965Sjdp      if (! append_type (info, " /*"))
1221130561Sobrien	return FALSE;
122233965Sjdp
122333965Sjdp      if (size != 0)
122433965Sjdp	{
122533965Sjdp	  char ab[20];
122633965Sjdp
122733965Sjdp	  sprintf (ab, "%u", size);
122833965Sjdp	  if (! append_type (info, " size ")
122933965Sjdp	      || ! append_type (info, ab))
1230130561Sobrien	    return FALSE;
123133965Sjdp	}
123233965Sjdp
123333965Sjdp      if (vptr)
123433965Sjdp	{
123533965Sjdp	  if (! append_type (info, " vtable "))
1236130561Sobrien	    return FALSE;
123733965Sjdp	  if (ownvptr)
123833965Sjdp	    {
123933965Sjdp	      if (! append_type (info, "self "))
1240130561Sobrien		return FALSE;
124133965Sjdp	    }
124233965Sjdp	  else
124333965Sjdp	    {
124433965Sjdp	      if (! append_type (info, tv)
124533965Sjdp		  || ! append_type (info, " "))
1246130561Sobrien		return FALSE;
124733965Sjdp	    }
124833965Sjdp	}
124933965Sjdp
125033965Sjdp      if (tag != NULL)
125133965Sjdp	{
125233965Sjdp	  char ab[30];
125333965Sjdp
125433965Sjdp	  sprintf (ab, " id %u", id);
125533965Sjdp	  if (! append_type (info, ab))
1256130561Sobrien	    return FALSE;
125733965Sjdp	}
125833965Sjdp
125933965Sjdp      if (! append_type (info, " */"))
1260130561Sobrien	return FALSE;
126133965Sjdp    }
126233965Sjdp
126333965Sjdp  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
126433965Sjdp
126533965Sjdp  return (append_type (info, "\n")
126633965Sjdp	  && indent_type (info));
126733965Sjdp}
126833965Sjdp
126933965Sjdp/* Add a static member to a class.  */
127033965Sjdp
1271130561Sobrienstatic bfd_boolean
1272130561Sobrienpr_class_static_member (void *p, const char *name, const char *physname,
1273130561Sobrien			enum debug_visibility visibility)
127433965Sjdp{
127533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
127633965Sjdp  char *t;
127733965Sjdp
127833965Sjdp  if (! substitute_type (info, name))
1279130561Sobrien    return FALSE;
128033965Sjdp
128133965Sjdp  if (! prepend_type (info, "static ")
128233965Sjdp      || ! append_type (info, "; /* ")
128333965Sjdp      || ! append_type (info, physname)
128433965Sjdp      || ! append_type (info, " */\n")
128533965Sjdp      || ! indent_type (info))
1286130561Sobrien    return FALSE;
128733965Sjdp
128833965Sjdp  t = pop_type (info);
128933965Sjdp  if (t == NULL)
1290130561Sobrien    return FALSE;
129133965Sjdp
129233965Sjdp  if (! pr_fix_visibility (info, visibility))
1293130561Sobrien    return FALSE;
129433965Sjdp
129533965Sjdp  return append_type (info, t);
129633965Sjdp}
129733965Sjdp
129833965Sjdp/* Add a base class to a class.  */
129933965Sjdp
1300130561Sobrienstatic bfd_boolean
1301130561Sobrienpr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
1302130561Sobrien		    enum debug_visibility visibility)
130333965Sjdp{
130433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
130533965Sjdp  char *t;
130633965Sjdp  const char *prefix;
130733965Sjdp  char ab[20];
130833965Sjdp  char *s, *l, *n;
130933965Sjdp
131033965Sjdp  assert (info->stack != NULL && info->stack->next != NULL);
131133965Sjdp
131233965Sjdp  if (! substitute_type (info, ""))
1313130561Sobrien    return FALSE;
131433965Sjdp
131533965Sjdp  t = pop_type (info);
131633965Sjdp  if (t == NULL)
1317130561Sobrien    return FALSE;
131833965Sjdp
131933965Sjdp  if (strncmp (t, "class ", sizeof "class " - 1) == 0)
132033965Sjdp    t += sizeof "class " - 1;
132133965Sjdp
132233965Sjdp  /* Push it back on to take advantage of the prepend_type and
132333965Sjdp     append_type routines.  */
132433965Sjdp  if (! push_type (info, t))
1325130561Sobrien    return FALSE;
132633965Sjdp
132733965Sjdp  if (virtual)
132833965Sjdp    {
132933965Sjdp      if (! prepend_type (info, "virtual "))
1330130561Sobrien	return FALSE;
133133965Sjdp    }
133233965Sjdp
133333965Sjdp  switch (visibility)
133433965Sjdp    {
133533965Sjdp    case DEBUG_VISIBILITY_PUBLIC:
133633965Sjdp      prefix = "public ";
133733965Sjdp      break;
133833965Sjdp    case DEBUG_VISIBILITY_PROTECTED:
133933965Sjdp      prefix = "protected ";
134033965Sjdp      break;
134133965Sjdp    case DEBUG_VISIBILITY_PRIVATE:
134233965Sjdp      prefix = "private ";
134333965Sjdp      break;
134433965Sjdp    default:
134533965Sjdp      prefix = "/* unknown visibility */ ";
134633965Sjdp      break;
134733965Sjdp    }
134833965Sjdp
134933965Sjdp  if (! prepend_type (info, prefix))
1350130561Sobrien    return FALSE;
135133965Sjdp
135233965Sjdp  if (bitpos != 0)
135333965Sjdp    {
1354130561Sobrien      print_vma (bitpos, ab, TRUE, FALSE);
135533965Sjdp      if (! append_type (info, " /* bitpos ")
135633965Sjdp	  || ! append_type (info, ab)
135733965Sjdp	  || ! append_type (info, " */"))
1358130561Sobrien	return FALSE;
135933965Sjdp    }
136033965Sjdp
136133965Sjdp  /* Now the top of the stack is something like "public A / * bitpos
136233965Sjdp     10 * /".  The next element on the stack is something like "class
136333965Sjdp     xx { / * size 8 * /\n...".  We want to substitute the top of the
136433965Sjdp     stack in before the {.  */
136533965Sjdp  s = strchr (info->stack->next->type, '{');
136633965Sjdp  assert (s != NULL);
136733965Sjdp  --s;
136833965Sjdp
136933965Sjdp  /* If there is already a ':', then we already have a baseclass, and
137033965Sjdp     we must append this one after a comma.  */
137133965Sjdp  for (l = info->stack->next->type; l != s; l++)
137233965Sjdp    if (*l == ':')
137333965Sjdp      break;
137433965Sjdp  if (! prepend_type (info, l == s ? " : " : ", "))
1375130561Sobrien    return FALSE;
137633965Sjdp
137733965Sjdp  t = pop_type (info);
137833965Sjdp  if (t == NULL)
1379130561Sobrien    return FALSE;
138033965Sjdp
138133965Sjdp  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
138233965Sjdp  memcpy (n, info->stack->type, s - info->stack->type);
138333965Sjdp  strcpy (n + (s - info->stack->type), t);
138433965Sjdp  strcat (n, s);
138533965Sjdp
138633965Sjdp  free (info->stack->type);
138733965Sjdp  info->stack->type = n;
138833965Sjdp
138933965Sjdp  free (t);
139033965Sjdp
1391130561Sobrien  return TRUE;
139233965Sjdp}
139333965Sjdp
139433965Sjdp/* Start adding a method to a class.  */
139533965Sjdp
1396130561Sobrienstatic bfd_boolean
1397130561Sobrienpr_class_start_method (void *p, const char *name)
139833965Sjdp{
139933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
140033965Sjdp
140133965Sjdp  assert (info->stack != NULL);
140233965Sjdp  info->stack->method = name;
1403130561Sobrien  return TRUE;
140433965Sjdp}
140533965Sjdp
140633965Sjdp/* Add a variant to a method.  */
140733965Sjdp
1408130561Sobrienstatic bfd_boolean
1409130561Sobrienpr_class_method_variant (void *p, const char *physname,
1410130561Sobrien			 enum debug_visibility visibility,
1411130561Sobrien			 bfd_boolean constp, bfd_boolean volatilep,
1412130561Sobrien			 bfd_vma voffset, bfd_boolean context)
141333965Sjdp{
141433965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
141533965Sjdp  char *method_type;
141633965Sjdp  char *context_type;
141733965Sjdp
141833965Sjdp  assert (info->stack != NULL);
141933965Sjdp  assert (info->stack->next != NULL);
142033965Sjdp
142133965Sjdp  /* Put the const and volatile qualifiers on the type.  */
142233965Sjdp  if (volatilep)
142333965Sjdp    {
142433965Sjdp      if (! append_type (info, " volatile"))
1425130561Sobrien	return FALSE;
142633965Sjdp    }
142733965Sjdp  if (constp)
142833965Sjdp    {
142933965Sjdp      if (! append_type (info, " const"))
1430130561Sobrien	return FALSE;
143133965Sjdp    }
143233965Sjdp
143333965Sjdp  /* Stick the name of the method into its type.  */
143433965Sjdp  if (! substitute_type (info,
143533965Sjdp			 (context
143633965Sjdp			  ? info->stack->next->next->method
143733965Sjdp			  : info->stack->next->method)))
1438130561Sobrien    return FALSE;
143933965Sjdp
144033965Sjdp  /* Get the type.  */
144133965Sjdp  method_type = pop_type (info);
144233965Sjdp  if (method_type == NULL)
1443130561Sobrien    return FALSE;
144433965Sjdp
144533965Sjdp  /* Pull off the context type if there is one.  */
144633965Sjdp  if (! context)
144733965Sjdp    context_type = NULL;
144833965Sjdp  else
144933965Sjdp    {
145033965Sjdp      context_type = pop_type (info);
145133965Sjdp      if (context_type == NULL)
1452130561Sobrien	return FALSE;
145333965Sjdp    }
145433965Sjdp
145533965Sjdp  /* Now the top of the stack is the class.  */
145633965Sjdp
145733965Sjdp  if (! pr_fix_visibility (info, visibility))
1458130561Sobrien    return FALSE;
145933965Sjdp
146033965Sjdp  if (! append_type (info, method_type)
146133965Sjdp      || ! append_type (info, " /* ")
146233965Sjdp      || ! append_type (info, physname)
146333965Sjdp      || ! append_type (info, " "))
1464130561Sobrien    return FALSE;
146533965Sjdp  if (context || voffset != 0)
146633965Sjdp    {
146733965Sjdp      char ab[20];
146833965Sjdp
146933965Sjdp      if (context)
147033965Sjdp	{
147133965Sjdp	  if (! append_type (info, "context ")
147233965Sjdp	      || ! append_type (info, context_type)
147333965Sjdp	      || ! append_type (info, " "))
1474130561Sobrien	    return FALSE;
147533965Sjdp	}
1476130561Sobrien      print_vma (voffset, ab, TRUE, FALSE);
147733965Sjdp      if (! append_type (info, "voffset ")
147833965Sjdp	  || ! append_type (info, ab))
1479130561Sobrien	return FALSE;
148033965Sjdp    }
148133965Sjdp
148233965Sjdp  return (append_type (info, " */;\n")
148333965Sjdp	  && indent_type (info));
148433965Sjdp}
148533965Sjdp
148633965Sjdp/* Add a static variant to a method.  */
148733965Sjdp
1488130561Sobrienstatic bfd_boolean
1489130561Sobrienpr_class_static_method_variant (void *p, const char *physname,
1490130561Sobrien				enum debug_visibility visibility,
1491130561Sobrien				bfd_boolean constp, bfd_boolean volatilep)
149233965Sjdp{
149333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
149433965Sjdp  char *method_type;
149533965Sjdp
149633965Sjdp  assert (info->stack != NULL);
149733965Sjdp  assert (info->stack->next != NULL);
149833965Sjdp  assert (info->stack->next->method != NULL);
149933965Sjdp
150033965Sjdp  /* Put the const and volatile qualifiers on the type.  */
150133965Sjdp  if (volatilep)
150233965Sjdp    {
150333965Sjdp      if (! append_type (info, " volatile"))
1504130561Sobrien	return FALSE;
150533965Sjdp    }
150633965Sjdp  if (constp)
150733965Sjdp    {
150833965Sjdp      if (! append_type (info, " const"))
1509130561Sobrien	return FALSE;
151033965Sjdp    }
151133965Sjdp
151233965Sjdp  /* Mark it as static.  */
151333965Sjdp  if (! prepend_type (info, "static "))
1514130561Sobrien    return FALSE;
151533965Sjdp
151633965Sjdp  /* Stick the name of the method into its type.  */
151733965Sjdp  if (! substitute_type (info, info->stack->next->method))
1518130561Sobrien    return FALSE;
151933965Sjdp
152033965Sjdp  /* Get the type.  */
152133965Sjdp  method_type = pop_type (info);
152233965Sjdp  if (method_type == NULL)
1523130561Sobrien    return FALSE;
152433965Sjdp
152533965Sjdp  /* Now the top of the stack is the class.  */
152633965Sjdp
152733965Sjdp  if (! pr_fix_visibility (info, visibility))
1528130561Sobrien    return FALSE;
152933965Sjdp
153033965Sjdp  return (append_type (info, method_type)
153133965Sjdp	  && append_type (info, " /* ")
153233965Sjdp	  && append_type (info, physname)
153333965Sjdp	  && append_type (info, " */;\n")
153433965Sjdp	  && indent_type (info));
153533965Sjdp}
153633965Sjdp
153733965Sjdp/* Finish up a method.  */
153833965Sjdp
1539130561Sobrienstatic bfd_boolean
1540130561Sobrienpr_class_end_method (void *p)
154133965Sjdp{
154233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
154333965Sjdp
154433965Sjdp  info->stack->method = NULL;
1545130561Sobrien  return TRUE;
154633965Sjdp}
154733965Sjdp
154833965Sjdp/* Finish up a class.  */
154933965Sjdp
1550130561Sobrienstatic bfd_boolean
1551130561Sobrienpr_end_class_type (void *p)
155233965Sjdp{
155333965Sjdp  return pr_end_struct_type (p);
155433965Sjdp}
155533965Sjdp
155633965Sjdp/* Push a type on the stack using a typedef name.  */
155733965Sjdp
1558130561Sobrienstatic bfd_boolean
1559130561Sobrienpr_typedef_type (void *p, const char *name)
156033965Sjdp{
156133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
156233965Sjdp
156333965Sjdp  return push_type (info, name);
156433965Sjdp}
156533965Sjdp
156633965Sjdp/* Push a type on the stack using a tag name.  */
156733965Sjdp
1568130561Sobrienstatic bfd_boolean
1569130561Sobrienpr_tag_type (void *p, const char *name, unsigned int id,
1570130561Sobrien	     enum debug_type_kind kind)
157133965Sjdp{
157233965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
157333965Sjdp  const char *t, *tag;
157433965Sjdp  char idbuf[20];
157533965Sjdp
157633965Sjdp  switch (kind)
157733965Sjdp    {
157833965Sjdp    case DEBUG_KIND_STRUCT:
157933965Sjdp      t = "struct ";
158033965Sjdp      break;
158133965Sjdp    case DEBUG_KIND_UNION:
158233965Sjdp      t = "union ";
158333965Sjdp      break;
158433965Sjdp    case DEBUG_KIND_ENUM:
158533965Sjdp      t = "enum ";
158633965Sjdp      break;
158733965Sjdp    case DEBUG_KIND_CLASS:
158833965Sjdp      t = "class ";
158933965Sjdp      break;
159033965Sjdp    case DEBUG_KIND_UNION_CLASS:
159133965Sjdp      t = "union class ";
159233965Sjdp      break;
159333965Sjdp    default:
159433965Sjdp      abort ();
1595130561Sobrien      return FALSE;
159633965Sjdp    }
159733965Sjdp
159833965Sjdp  if (! push_type (info, t))
1599130561Sobrien    return FALSE;
160033965Sjdp  if (name != NULL)
160133965Sjdp    tag = name;
160233965Sjdp  else
160333965Sjdp    {
160433965Sjdp      sprintf (idbuf, "%%anon%u", id);
160533965Sjdp      tag = idbuf;
160633965Sjdp    }
160733965Sjdp
160833965Sjdp  if (! append_type (info, tag))
1609130561Sobrien    return FALSE;
161033965Sjdp  if (name != NULL && kind != DEBUG_KIND_ENUM)
161133965Sjdp    {
161233965Sjdp      sprintf (idbuf, " /* id %u */", id);
161333965Sjdp      if (! append_type (info, idbuf))
1614130561Sobrien	return FALSE;
161533965Sjdp    }
161633965Sjdp
1617130561Sobrien  return TRUE;
161833965Sjdp}
161933965Sjdp
162033965Sjdp/* Output a typedef.  */
162133965Sjdp
1622130561Sobrienstatic bfd_boolean
1623130561Sobrienpr_typdef (void *p, const char *name)
162433965Sjdp{
162533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
162633965Sjdp  char *s;
162733965Sjdp
162833965Sjdp  if (! substitute_type (info, name))
1629130561Sobrien    return FALSE;
163033965Sjdp
163133965Sjdp  s = pop_type (info);
163233965Sjdp  if (s == NULL)
1633130561Sobrien    return FALSE;
163433965Sjdp
163533965Sjdp  indent (info);
163633965Sjdp  fprintf (info->f, "typedef %s;\n", s);
163733965Sjdp
163833965Sjdp  free (s);
163933965Sjdp
1640130561Sobrien  return TRUE;
164133965Sjdp}
164233965Sjdp
164333965Sjdp/* Output a tag.  The tag should already be in the string on the
164433965Sjdp   stack, so all we have to do here is print it out.  */
164533965Sjdp
1646130561Sobrienstatic bfd_boolean
1647130561Sobrienpr_tag (void *p, const char *name ATTRIBUTE_UNUSED)
164833965Sjdp{
164933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
165033965Sjdp  char *t;
165133965Sjdp
165233965Sjdp  t = pop_type (info);
165333965Sjdp  if (t == NULL)
1654130561Sobrien    return FALSE;
165533965Sjdp
165633965Sjdp  indent (info);
165733965Sjdp  fprintf (info->f, "%s;\n", t);
165833965Sjdp
165933965Sjdp  free (t);
166033965Sjdp
1661130561Sobrien  return TRUE;
166233965Sjdp}
166333965Sjdp
166433965Sjdp/* Output an integer constant.  */
166533965Sjdp
1666130561Sobrienstatic bfd_boolean
1667130561Sobrienpr_int_constant (void *p, const char *name, bfd_vma val)
166833965Sjdp{
166933965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
167033965Sjdp  char ab[20];
167133965Sjdp
167233965Sjdp  indent (info);
1673130561Sobrien  print_vma (val, ab, FALSE, FALSE);
167433965Sjdp  fprintf (info->f, "const int %s = %s;\n", name, ab);
1675130561Sobrien  return TRUE;
167633965Sjdp}
167733965Sjdp
167833965Sjdp/* Output a floating point constant.  */
167933965Sjdp
1680130561Sobrienstatic bfd_boolean
1681130561Sobrienpr_float_constant (void *p, const char *name, double val)
168233965Sjdp{
168333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
168433965Sjdp
168533965Sjdp  indent (info);
168633965Sjdp  fprintf (info->f, "const double %s = %g;\n", name, val);
1687130561Sobrien  return TRUE;
168833965Sjdp}
168933965Sjdp
169033965Sjdp/* Output a typed constant.  */
169133965Sjdp
1692130561Sobrienstatic bfd_boolean
1693130561Sobrienpr_typed_constant (void *p, const char *name, bfd_vma val)
169433965Sjdp{
169533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
169633965Sjdp  char *t;
169733965Sjdp  char ab[20];
169833965Sjdp
169933965Sjdp  t = pop_type (info);
170033965Sjdp  if (t == NULL)
1701130561Sobrien    return FALSE;
170233965Sjdp
170333965Sjdp  indent (info);
1704130561Sobrien  print_vma (val, ab, FALSE, FALSE);
170533965Sjdp  fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
170633965Sjdp
170733965Sjdp  free (t);
170833965Sjdp
1709130561Sobrien  return TRUE;
171033965Sjdp}
171133965Sjdp
171233965Sjdp/* Output a variable.  */
171333965Sjdp
1714130561Sobrienstatic bfd_boolean
1715130561Sobrienpr_variable (void *p, const char *name, enum debug_var_kind kind,
1716130561Sobrien	     bfd_vma val)
171733965Sjdp{
171833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
171933965Sjdp  char *t;
172033965Sjdp  char ab[20];
172133965Sjdp
172233965Sjdp  if (! substitute_type (info, name))
1723130561Sobrien    return FALSE;
172433965Sjdp
172533965Sjdp  t = pop_type (info);
172633965Sjdp  if (t == NULL)
1727130561Sobrien    return FALSE;
172833965Sjdp
172933965Sjdp  indent (info);
173033965Sjdp  switch (kind)
173133965Sjdp    {
173233965Sjdp    case DEBUG_STATIC:
173333965Sjdp    case DEBUG_LOCAL_STATIC:
173433965Sjdp      fprintf (info->f, "static ");
173533965Sjdp      break;
173633965Sjdp    case DEBUG_REGISTER:
173733965Sjdp      fprintf (info->f, "register ");
173833965Sjdp      break;
173933965Sjdp    default:
174033965Sjdp      break;
174133965Sjdp    }
1742130561Sobrien  print_vma (val, ab, TRUE, TRUE);
174333965Sjdp  fprintf (info->f, "%s /* %s */;\n", t, ab);
174433965Sjdp
174533965Sjdp  free (t);
174633965Sjdp
1747130561Sobrien  return TRUE;
174833965Sjdp}
174933965Sjdp
175033965Sjdp/* Start outputting a function.  */
175133965Sjdp
1752130561Sobrienstatic bfd_boolean
1753130561Sobrienpr_start_function (void *p, const char *name, bfd_boolean global)
175433965Sjdp{
175533965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
175633965Sjdp  char *t;
175733965Sjdp
175833965Sjdp  if (! substitute_type (info, name))
1759130561Sobrien    return FALSE;
176033965Sjdp
176133965Sjdp  t = pop_type (info);
176233965Sjdp  if (t == NULL)
1763130561Sobrien    return FALSE;
176433965Sjdp
176533965Sjdp  indent (info);
176633965Sjdp  if (! global)
176733965Sjdp    fprintf (info->f, "static ");
176833965Sjdp  fprintf (info->f, "%s (", t);
176933965Sjdp
177033965Sjdp  info->parameter = 1;
177133965Sjdp
1772130561Sobrien  return TRUE;
177333965Sjdp}
177433965Sjdp
177533965Sjdp/* Output a function parameter.  */
177633965Sjdp
1777130561Sobrienstatic bfd_boolean
1778130561Sobrienpr_function_parameter (void *p, const char *name,
1779130561Sobrien		       enum debug_parm_kind kind, bfd_vma val)
178033965Sjdp{
178133965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
178233965Sjdp  char *t;
178333965Sjdp  char ab[20];
178433965Sjdp
178533965Sjdp  if (kind == DEBUG_PARM_REFERENCE
178633965Sjdp      || kind == DEBUG_PARM_REF_REG)
178733965Sjdp    {
178833965Sjdp      if (! pr_reference_type (p))
1789130561Sobrien	return FALSE;
179033965Sjdp    }
179133965Sjdp
179233965Sjdp  if (! substitute_type (info, name))
1793130561Sobrien    return FALSE;
179433965Sjdp
179533965Sjdp  t = pop_type (info);
179633965Sjdp  if (t == NULL)
1797130561Sobrien    return FALSE;
179833965Sjdp
179933965Sjdp  if (info->parameter != 1)
180033965Sjdp    fprintf (info->f, ", ");
180133965Sjdp
180233965Sjdp  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
180333965Sjdp    fprintf (info->f, "register ");
180433965Sjdp
1805130561Sobrien  print_vma (val, ab, TRUE, TRUE);
180633965Sjdp  fprintf (info->f, "%s /* %s */", t, ab);
180733965Sjdp
180833965Sjdp  free (t);
180933965Sjdp
181033965Sjdp  ++info->parameter;
181133965Sjdp
1812130561Sobrien  return TRUE;
181333965Sjdp}
181433965Sjdp
181533965Sjdp/* Start writing out a block.  */
181633965Sjdp
1817130561Sobrienstatic bfd_boolean
1818130561Sobrienpr_start_block (void *p, bfd_vma addr)
181933965Sjdp{
182033965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
182133965Sjdp  char ab[20];
182233965Sjdp
182333965Sjdp  if (info->parameter > 0)
182433965Sjdp    {
182533965Sjdp      fprintf (info->f, ")\n");
182633965Sjdp      info->parameter = 0;
182733965Sjdp    }
182833965Sjdp
182933965Sjdp  indent (info);
1830130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
183133965Sjdp  fprintf (info->f, "{ /* %s */\n", ab);
183233965Sjdp
183333965Sjdp  info->indent += 2;
183433965Sjdp
1835130561Sobrien  return TRUE;
183633965Sjdp}
183733965Sjdp
183833965Sjdp/* Write out line number information.  */
183933965Sjdp
1840130561Sobrienstatic bfd_boolean
1841130561Sobrienpr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
184233965Sjdp{
184333965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
184433965Sjdp  char ab[20];
184533965Sjdp
184633965Sjdp  indent (info);
1847130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
184833965Sjdp  fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
184933965Sjdp
1850130561Sobrien  return TRUE;
185133965Sjdp}
185233965Sjdp
185333965Sjdp/* Finish writing out a block.  */
185433965Sjdp
1855130561Sobrienstatic bfd_boolean
1856130561Sobrienpr_end_block (void *p, bfd_vma addr)
185733965Sjdp{
185833965Sjdp  struct pr_handle *info = (struct pr_handle *) p;
185933965Sjdp  char ab[20];
186033965Sjdp
186133965Sjdp  info->indent -= 2;
186233965Sjdp
186333965Sjdp  indent (info);
1864130561Sobrien  print_vma (addr, ab, TRUE, TRUE);
186533965Sjdp  fprintf (info->f, "} /* %s */\n", ab);
186633965Sjdp
1867130561Sobrien  return TRUE;
186833965Sjdp}
186933965Sjdp
187033965Sjdp/* Finish writing out a function.  */
187133965Sjdp
1872130561Sobrienstatic bfd_boolean
1873130561Sobrienpr_end_function (void *p ATTRIBUTE_UNUSED)
187433965Sjdp{
1875130561Sobrien  return TRUE;
187633965Sjdp}
1877130561Sobrien
1878130561Sobrien/* Tags style generation functions start here.  */
1879130561Sobrien
1880130561Sobrien/* Variables for address to line translation.  */
1881130561Sobrienstatic bfd_vma pc;
1882130561Sobrienstatic const char *filename;
1883130561Sobrienstatic const char *functionname;
1884130561Sobrienstatic unsigned int line;
1885130561Sobrienstatic bfd_boolean found;
1886130561Sobrien
1887130561Sobrien/* Look for an address in a section.  This is called via
1888130561Sobrien   bfd_map_over_sections.  */
1889130561Sobrien
1890130561Sobrienstatic void
1891130561Sobrienfind_address_in_section (bfd *abfd, asection *section, void *data)
1892130561Sobrien{
1893130561Sobrien  bfd_vma vma;
1894130561Sobrien  bfd_size_type size;
1895130561Sobrien  asymbol **syms = (asymbol **) data;
1896130561Sobrien
1897130561Sobrien  if (found)
1898130561Sobrien    return;
1899130561Sobrien
1900130561Sobrien  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
1901130561Sobrien    return;
1902130561Sobrien
1903130561Sobrien  vma = bfd_get_section_vma (abfd, section);
1904130561Sobrien  if (pc < vma)
1905130561Sobrien    return;
1906130561Sobrien
1907130561Sobrien  size = bfd_get_section_size_before_reloc (section);
1908130561Sobrien  if (pc >= vma + size)
1909130561Sobrien    return;
1910130561Sobrien
1911130561Sobrien  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
1912130561Sobrien				 &filename, &functionname, &line);
1913130561Sobrien}
1914130561Sobrien
1915130561Sobrienstatic void
1916130561Sobrientranslate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms)
1917130561Sobrien{
1918130561Sobrien  pc = bfd_scan_vma (addr_hex, NULL, 16);
1919130561Sobrien  found = FALSE;
1920130561Sobrien  bfd_map_over_sections (abfd, find_address_in_section, syms);
1921130561Sobrien
1922130561Sobrien  if (! found)
1923130561Sobrien    fprintf (f, "??");
1924130561Sobrien  else
1925130561Sobrien    fprintf (f, "%u", line);
1926130561Sobrien}
1927130561Sobrien
1928130561Sobrien/* Start a new compilation unit.  */
1929130561Sobrien
1930130561Sobrienstatic bfd_boolean
1931130561Sobrientg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED)
1932130561Sobrien{
1933130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1934130561Sobrien
1935130561Sobrien  fprintf (stderr, "New compilation unit: %s\n", filename);
1936130561Sobrien
1937130561Sobrien  free (info->filename);
1938130561Sobrien  /* Should it be relative? best way to do it here?.  */
1939130561Sobrien  info->filename = strdup (filename);
1940130561Sobrien
1941130561Sobrien  return TRUE;
1942130561Sobrien}
1943130561Sobrien
1944130561Sobrien/* Start a source file within a compilation unit.  */
1945130561Sobrien
1946130561Sobrienstatic bfd_boolean
1947130561Sobrientg_start_source (void *p, const char *filename)
1948130561Sobrien{
1949130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1950130561Sobrien
1951130561Sobrien  free (info->filename);
1952130561Sobrien  /* Should it be relative? best way to do it here?.  */
1953130561Sobrien  info->filename = strdup (filename);
1954130561Sobrien
1955130561Sobrien  return TRUE;
1956130561Sobrien}
1957130561Sobrien
1958130561Sobrien/* Push an enum type onto the type stack.  */
1959130561Sobrien
1960130561Sobrienstatic bfd_boolean
1961130561Sobrientg_enum_type (void *p, const char *tag, const char **names,
1962130561Sobrien	      bfd_signed_vma *values)
1963130561Sobrien{
1964130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
1965130561Sobrien  unsigned int i;
1966130561Sobrien  const char *name;
1967130561Sobrien  char ab[20];
1968130561Sobrien
1969130561Sobrien  if (! pr_enum_type (p, tag, names, values))
1970130561Sobrien    return FALSE;
1971130561Sobrien
1972130561Sobrien  name = tag ? tag : "unknown";
1973130561Sobrien  /* Generate an entry for the enum.  */
1974130561Sobrien  if (tag)
1975130561Sobrien    fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag,
1976130561Sobrien	     info->filename, info->stack->type);
1977130561Sobrien
1978130561Sobrien  /* Generate entries for the values.  */
1979130561Sobrien  if (names != NULL)
1980130561Sobrien    {
1981130561Sobrien      for (i = 0; names[i] != NULL; i++)
1982130561Sobrien	{
1983130561Sobrien	  print_vma (values[i], ab, FALSE, FALSE);
1984130561Sobrien	  fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n",
1985130561Sobrien		   names[i], info->filename, name, ab);
1986130561Sobrien	}
1987130561Sobrien    }
1988130561Sobrien
1989130561Sobrien  return TRUE;
1990130561Sobrien}
1991130561Sobrien
1992130561Sobrien/* Start accumulating a struct type.  */
1993130561Sobrien
1994130561Sobrienstatic bfd_boolean
1995130561Sobrientg_start_struct_type (void *p, const char *tag, unsigned int id,
1996130561Sobrien		      bfd_boolean structp,
1997130561Sobrien		      unsigned int size ATTRIBUTE_UNUSED)
1998130561Sobrien{
1999130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2000130561Sobrien  const char *name;
2001130561Sobrien  char idbuf[20];
2002130561Sobrien
2003130561Sobrien  if (tag != NULL)
2004130561Sobrien    name = tag;
2005130561Sobrien  else
2006130561Sobrien    {
2007130561Sobrien      name = idbuf;
2008130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2009130561Sobrien    }
2010130561Sobrien
2011130561Sobrien  if (! push_type (info, name))
2012130561Sobrien    return FALSE;
2013130561Sobrien
2014130561Sobrien  info->stack->flavor = structp ? "struct" : "union";
2015130561Sobrien
2016130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename,
2017130561Sobrien	   info->stack->flavor[0]);
2018130561Sobrien
2019130561Sobrien  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
2020130561Sobrien
2021130561Sobrien  return indent_type (info);
2022130561Sobrien}
2023130561Sobrien
2024130561Sobrien/* Output the visibility of a field in a struct.  */
2025130561Sobrien
2026130561Sobrienstatic bfd_boolean
2027130561Sobrientg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
2028130561Sobrien{
2029130561Sobrien  assert (info->stack != NULL);
2030130561Sobrien
2031130561Sobrien  if (info->stack->visibility == visibility)
2032130561Sobrien    return TRUE;
2033130561Sobrien
2034130561Sobrien  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
2035130561Sobrien
2036130561Sobrien  info->stack->visibility = visibility;
2037130561Sobrien
2038130561Sobrien  return TRUE;
2039130561Sobrien}
2040130561Sobrien
2041130561Sobrien/* Add a field to a struct type.  */
2042130561Sobrien
2043130561Sobrienstatic bfd_boolean
2044130561Sobrientg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED,
2045130561Sobrien		 bfd_vma bitsize ATTRIBUTE_UNUSED,
2046130561Sobrien		 enum debug_visibility visibility)
2047130561Sobrien{
2048130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2049130561Sobrien  char *t;
2050130561Sobrien
2051130561Sobrien  t = pop_type (info);
2052130561Sobrien  if (t == NULL)
2053130561Sobrien    return FALSE;
2054130561Sobrien
2055130561Sobrien  if (! tg_fix_visibility (info, visibility))
2056130561Sobrien    return FALSE;
2057130561Sobrien
2058130561Sobrien  /* It happens, a bug? */
2059130561Sobrien  if (! name[0])
2060130561Sobrien    return TRUE;
2061130561Sobrien
2062130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
2063130561Sobrien	   name, info->filename, t, info->stack->flavor, info->stack->type,
2064130561Sobrien	   visibility_name (visibility));
2065130561Sobrien
2066130561Sobrien  return TRUE;
2067130561Sobrien}
2068130561Sobrien
2069130561Sobrien/* Finish a struct type.  */
2070130561Sobrien
2071130561Sobrienstatic bfd_boolean
2072130561Sobrientg_end_struct_type (void *p ATTRIBUTE_UNUSED)
2073130561Sobrien{
2074130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2075130561Sobrien  assert (info->stack != NULL);
2076130561Sobrien
2077130561Sobrien  return TRUE;
2078130561Sobrien}
2079130561Sobrien
2080130561Sobrien/* Start a class type.  */
2081130561Sobrien
2082130561Sobrienstatic bfd_boolean
2083130561Sobrientg_start_class_type (void *p, const char *tag, unsigned int id,
2084130561Sobrien		     bfd_boolean structp, unsigned int size,
2085130561Sobrien		     bfd_boolean vptr, bfd_boolean ownvptr)
2086130561Sobrien{
2087130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2088130561Sobrien  char *tv = NULL;
2089130561Sobrien  const char *name;
2090130561Sobrien
2091130561Sobrien  info->indent += 2;
2092130561Sobrien
2093130561Sobrien  if (vptr && ! ownvptr)
2094130561Sobrien    {
2095130561Sobrien      tv = pop_type (info);
2096130561Sobrien      if (tv == NULL)
2097130561Sobrien	return FALSE;
2098130561Sobrien    }
2099130561Sobrien
2100130561Sobrien  if (tag != NULL)
2101130561Sobrien    name = tag;
2102130561Sobrien  else
2103130561Sobrien    {
2104130561Sobrien      char idbuf[20];
2105130561Sobrien
2106130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2107130561Sobrien      name = idbuf;
2108130561Sobrien    }
2109130561Sobrien
2110130561Sobrien  if (! push_type (info, name))
2111130561Sobrien    return FALSE;
2112130561Sobrien
2113130561Sobrien  info->stack->flavor = structp ? "class" : "union class";
2114130561Sobrien  info->stack->parents = NULL;
2115130561Sobrien  info->stack->num_parents = 0;
2116130561Sobrien
2117130561Sobrien  if (size != 0 || vptr || ownvptr || tag != NULL)
2118130561Sobrien    {
2119130561Sobrien      if (vptr)
2120130561Sobrien	{
2121130561Sobrien	  if (! append_type (info, " vtable "))
2122130561Sobrien	    return FALSE;
2123130561Sobrien	  if (ownvptr)
2124130561Sobrien	    {
2125130561Sobrien	      if (! append_type (info, "self "))
2126130561Sobrien		return FALSE;
2127130561Sobrien	    }
2128130561Sobrien	  else
2129130561Sobrien	    {
2130130561Sobrien	      if (! append_type (info, tv)
2131130561Sobrien		  || ! append_type (info, " "))
2132130561Sobrien		return FALSE;
2133130561Sobrien	    }
2134130561Sobrien	}
2135130561Sobrien    }
2136130561Sobrien
2137130561Sobrien  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
2138130561Sobrien
2139130561Sobrien  return TRUE;
2140130561Sobrien}
2141130561Sobrien
2142130561Sobrien/* Add a static member to a class.  */
2143130561Sobrien
2144130561Sobrienstatic bfd_boolean
2145130561Sobrientg_class_static_member (void *p, const char *name,
2146130561Sobrien			const char *physname ATTRIBUTE_UNUSED,
2147130561Sobrien			enum debug_visibility visibility)
2148130561Sobrien{
2149130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2150130561Sobrien  char *t;
2151130561Sobrien  int len_var, len_class;
2152130561Sobrien  char *full_name;
2153130561Sobrien
2154130561Sobrien  len_var = strlen (name);
2155130561Sobrien  len_class = strlen (info->stack->next->type);
2156130561Sobrien  full_name = (char *) xmalloc (len_var + len_class + 3);
2157130561Sobrien  if (! full_name)
2158130561Sobrien    return FALSE;
2159130561Sobrien  memcpy (full_name, info->stack->next->type, len_class);
2160130561Sobrien  memcpy (full_name + len_class, "::", 2);
2161130561Sobrien  memcpy (full_name + len_class + 2, name, len_var + 1);
2162130561Sobrien
2163130561Sobrien  if (! substitute_type (info, full_name))
2164130561Sobrien    return FALSE;
2165130561Sobrien
2166130561Sobrien  if (! prepend_type (info, "static "))
2167130561Sobrien    return FALSE;
2168130561Sobrien
2169130561Sobrien  t = pop_type (info);
2170130561Sobrien  if (t == NULL)
2171130561Sobrien    return FALSE;
2172130561Sobrien
2173130561Sobrien  if (! tg_fix_visibility (info, visibility))
2174130561Sobrien    return FALSE;
2175130561Sobrien
2176130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n",
2177130561Sobrien	   name, info->filename, t, info->stack->type,
2178130561Sobrien	   visibility_name (visibility));
2179130561Sobrien  free (t);
2180130561Sobrien  free (full_name);
2181130561Sobrien
2182130561Sobrien  return TRUE;
2183130561Sobrien}
2184130561Sobrien
2185130561Sobrien/* Add a base class to a class.  */
2186130561Sobrien
2187130561Sobrienstatic bfd_boolean
2188130561Sobrientg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
2189130561Sobrien		    bfd_boolean virtual, enum debug_visibility visibility)
2190130561Sobrien{
2191130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2192130561Sobrien  char *t;
2193130561Sobrien  const char *prefix;
2194130561Sobrien
2195130561Sobrien  assert (info->stack != NULL && info->stack->next != NULL);
2196130561Sobrien
2197130561Sobrien  t = pop_type (info);
2198130561Sobrien  if (t == NULL)
2199130561Sobrien    return FALSE;
2200130561Sobrien
2201130561Sobrien  if (strncmp (t, "class ", sizeof "class " - 1) == 0)
2202130561Sobrien    t += sizeof "class " - 1;
2203130561Sobrien
2204130561Sobrien  /* Push it back on to take advantage of the prepend_type and
2205130561Sobrien     append_type routines.  */
2206130561Sobrien  if (! push_type (info, t))
2207130561Sobrien    return FALSE;
2208130561Sobrien
2209130561Sobrien  if (virtual)
2210130561Sobrien    {
2211130561Sobrien      if (! prepend_type (info, "virtual "))
2212130561Sobrien	return FALSE;
2213130561Sobrien    }
2214130561Sobrien
2215130561Sobrien  switch (visibility)
2216130561Sobrien    {
2217130561Sobrien    case DEBUG_VISIBILITY_PUBLIC:
2218130561Sobrien      prefix = "public ";
2219130561Sobrien      break;
2220130561Sobrien    case DEBUG_VISIBILITY_PROTECTED:
2221130561Sobrien      prefix = "protected ";
2222130561Sobrien      break;
2223130561Sobrien    case DEBUG_VISIBILITY_PRIVATE:
2224130561Sobrien      prefix = "private ";
2225130561Sobrien      break;
2226130561Sobrien    default:
2227130561Sobrien      prefix = "/* unknown visibility */ ";
2228130561Sobrien      break;
2229130561Sobrien    }
2230130561Sobrien
2231130561Sobrien  if (! prepend_type (info, prefix))
2232130561Sobrien    return FALSE;
2233130561Sobrien
2234130561Sobrien  t = pop_type (info);
2235130561Sobrien  if (t == NULL)
2236130561Sobrien    return FALSE;
2237130561Sobrien
2238130561Sobrien  if (info->stack->num_parents && ! append_parent (info, ", "))
2239130561Sobrien    return FALSE;
2240130561Sobrien
2241130561Sobrien  if (! append_parent (info, t))
2242130561Sobrien    return FALSE;
2243130561Sobrien  info->stack->num_parents++;
2244130561Sobrien
2245130561Sobrien  free (t);
2246130561Sobrien
2247130561Sobrien  return TRUE;
2248130561Sobrien}
2249130561Sobrien
2250130561Sobrien/* Add a variant to a method.  */
2251130561Sobrien
2252130561Sobrienstatic bfd_boolean
2253130561Sobrientg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED,
2254130561Sobrien			 enum debug_visibility visibility,
2255130561Sobrien			 bfd_boolean constp, bfd_boolean volatilep,
2256130561Sobrien			 bfd_vma voffset ATTRIBUTE_UNUSED,
2257130561Sobrien			 bfd_boolean context)
2258130561Sobrien{
2259130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2260130561Sobrien  char *method_type;
2261130561Sobrien  char *context_type;
2262130561Sobrien  char *method_name;
2263130561Sobrien
2264130561Sobrien  assert (info->stack != NULL);
2265130561Sobrien  assert (info->stack->next != NULL);
2266130561Sobrien
2267130561Sobrien  /* Put the const and volatile qualifiers on the type.  */
2268130561Sobrien  if (volatilep)
2269130561Sobrien    {
2270130561Sobrien      if (! append_type (info, " volatile"))
2271130561Sobrien	return FALSE;
2272130561Sobrien    }
2273130561Sobrien  if (constp)
2274130561Sobrien    {
2275130561Sobrien      if (! append_type (info, " const"))
2276130561Sobrien	return FALSE;
2277130561Sobrien    }
2278130561Sobrien
2279130561Sobrien  method_name = strdup (context ? info->stack->next->next->method
2280130561Sobrien			: info->stack->next->method);
2281130561Sobrien
2282130561Sobrien  /* Stick the name of the method into its type.  */
2283130561Sobrien  if (! substitute_type (info, method_name))
2284130561Sobrien    return FALSE;
2285130561Sobrien
2286130561Sobrien  /* Get the type.  */
2287130561Sobrien  method_type = pop_type (info);
2288130561Sobrien  if (method_type == NULL)
2289130561Sobrien    return FALSE;
2290130561Sobrien
2291130561Sobrien  /* Pull off the context type if there is one.  */
2292130561Sobrien  if (! context)
2293130561Sobrien    context_type = NULL;
2294130561Sobrien  else
2295130561Sobrien    {
2296130561Sobrien      context_type = pop_type (info);
2297130561Sobrien      if (context_type == NULL)
2298130561Sobrien	return FALSE;
2299130561Sobrien    }
2300130561Sobrien
2301130561Sobrien  /* Now the top of the stack is the class.  */
2302130561Sobrien  if (! tg_fix_visibility (info, visibility))
2303130561Sobrien    return FALSE;
2304130561Sobrien
2305130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n",
2306130561Sobrien	   method_name, info->filename, method_type, info->stack->type);
2307130561Sobrien  free (method_type);
2308130561Sobrien  free (method_name);
2309130561Sobrien  free (context_type);
2310130561Sobrien
2311130561Sobrien  return TRUE;
2312130561Sobrien}
2313130561Sobrien
2314130561Sobrien/* Add a static variant to a method.  */
2315130561Sobrien
2316130561Sobrienstatic bfd_boolean
2317130561Sobrientg_class_static_method_variant (void *p,
2318130561Sobrien				const char *physname ATTRIBUTE_UNUSED,
2319130561Sobrien				enum debug_visibility visibility,
2320130561Sobrien				bfd_boolean constp, bfd_boolean volatilep)
2321130561Sobrien{
2322130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2323130561Sobrien  char *method_type;
2324130561Sobrien  char *method_name;
2325130561Sobrien
2326130561Sobrien  assert (info->stack != NULL);
2327130561Sobrien  assert (info->stack->next != NULL);
2328130561Sobrien  assert (info->stack->next->method != NULL);
2329130561Sobrien
2330130561Sobrien  /* Put the const and volatile qualifiers on the type.  */
2331130561Sobrien  if (volatilep)
2332130561Sobrien    {
2333130561Sobrien      if (! append_type (info, " volatile"))
2334130561Sobrien	return FALSE;
2335130561Sobrien    }
2336130561Sobrien  if (constp)
2337130561Sobrien    {
2338130561Sobrien      if (! append_type (info, " const"))
2339130561Sobrien	return FALSE;
2340130561Sobrien    }
2341130561Sobrien
2342130561Sobrien  /* Mark it as static.  */
2343130561Sobrien  if (! prepend_type (info, "static "))
2344130561Sobrien    return FALSE;
2345130561Sobrien
2346130561Sobrien  method_name = strdup (info->stack->next->method);
2347130561Sobrien  /* Stick the name of the method into its type.  */
2348130561Sobrien  if (! substitute_type (info, info->stack->next->method))
2349130561Sobrien    return FALSE;
2350130561Sobrien
2351130561Sobrien  /* Get the type.  */
2352130561Sobrien  method_type = pop_type (info);
2353130561Sobrien  if (method_type == NULL)
2354130561Sobrien    return FALSE;
2355130561Sobrien
2356130561Sobrien  /* Now the top of the stack is the class.  */
2357130561Sobrien  if (! tg_fix_visibility (info, visibility))
2358130561Sobrien    return FALSE;
2359130561Sobrien
2360130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n",
2361130561Sobrien	   method_name, info->filename, method_type, info->stack->type,
2362130561Sobrien	   visibility_name (visibility));
2363130561Sobrien  free (method_type);
2364130561Sobrien  free (method_name);
2365130561Sobrien
2366130561Sobrien  return TRUE;
2367130561Sobrien}
2368130561Sobrien
2369130561Sobrien/* Finish up a class.  */
2370130561Sobrien
2371130561Sobrienstatic bfd_boolean
2372130561Sobrientg_end_class_type (void *p)
2373130561Sobrien{
2374130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2375130561Sobrien
2376130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type,
2377130561Sobrien	   info->filename, info->stack->flavor);
2378130561Sobrien  if (info->stack->num_parents)
2379130561Sobrien    {
2380130561Sobrien      fprintf  (info->f, "\tinherits:%s", info->stack->parents);
2381130561Sobrien      free (info->stack->parents);
2382130561Sobrien    }
2383130561Sobrien  fputc ('\n', info->f);
2384130561Sobrien
2385130561Sobrien  return tg_end_struct_type (p);
2386130561Sobrien}
2387130561Sobrien
2388130561Sobrien/* Push a type on the stack using a tag name.  */
2389130561Sobrien
2390130561Sobrienstatic bfd_boolean
2391130561Sobrientg_tag_type (void *p, const char *name, unsigned int id,
2392130561Sobrien	     enum debug_type_kind kind)
2393130561Sobrien{
2394130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2395130561Sobrien  const char *t, *tag;
2396130561Sobrien  char idbuf[20];
2397130561Sobrien
2398130561Sobrien  switch (kind)
2399130561Sobrien    {
2400130561Sobrien    case DEBUG_KIND_STRUCT:
2401130561Sobrien      t = "struct ";
2402130561Sobrien      break;
2403130561Sobrien    case DEBUG_KIND_UNION:
2404130561Sobrien      t = "union ";
2405130561Sobrien      break;
2406130561Sobrien    case DEBUG_KIND_ENUM:
2407130561Sobrien      t = "enum ";
2408130561Sobrien      break;
2409130561Sobrien    case DEBUG_KIND_CLASS:
2410130561Sobrien      t = "class ";
2411130561Sobrien      break;
2412130561Sobrien    case DEBUG_KIND_UNION_CLASS:
2413130561Sobrien      t = "union class ";
2414130561Sobrien      break;
2415130561Sobrien    default:
2416130561Sobrien      abort ();
2417130561Sobrien      return FALSE;
2418130561Sobrien    }
2419130561Sobrien
2420130561Sobrien  if (! push_type (info, t))
2421130561Sobrien    return FALSE;
2422130561Sobrien  if (name != NULL)
2423130561Sobrien    tag = name;
2424130561Sobrien  else
2425130561Sobrien    {
2426130561Sobrien      sprintf (idbuf, "%%anon%u", id);
2427130561Sobrien      tag = idbuf;
2428130561Sobrien    }
2429130561Sobrien
2430130561Sobrien  if (! append_type (info, tag))
2431130561Sobrien    return FALSE;
2432130561Sobrien
2433130561Sobrien  return TRUE;
2434130561Sobrien}
2435130561Sobrien
2436130561Sobrien/* Output a typedef.  */
2437130561Sobrien
2438130561Sobrienstatic bfd_boolean
2439130561Sobrientg_typdef (void *p, const char *name)
2440130561Sobrien{
2441130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2442130561Sobrien  char *s;
2443130561Sobrien
2444130561Sobrien  s = pop_type (info);
2445130561Sobrien  if (s == NULL)
2446130561Sobrien    return FALSE;
2447130561Sobrien
2448130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name,
2449130561Sobrien	   info->filename, s);
2450130561Sobrien
2451130561Sobrien  free (s);
2452130561Sobrien
2453130561Sobrien  return TRUE;
2454130561Sobrien}
2455130561Sobrien
2456130561Sobrien/* Output a tag.  The tag should already be in the string on the
2457130561Sobrien   stack, so all we have to do here is print it out.  */
2458130561Sobrien
2459130561Sobrienstatic bfd_boolean
2460130561Sobrientg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED)
2461130561Sobrien{
2462130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2463130561Sobrien  char *t;
2464130561Sobrien
2465130561Sobrien  t = pop_type (info);
2466130561Sobrien  if (t == NULL)
2467130561Sobrien    return FALSE;
2468130561Sobrien  free (t);
2469130561Sobrien
2470130561Sobrien  return TRUE;
2471130561Sobrien}
2472130561Sobrien
2473130561Sobrien/* Output an integer constant.  */
2474130561Sobrien
2475130561Sobrienstatic bfd_boolean
2476130561Sobrientg_int_constant (void *p, const char *name, bfd_vma val)
2477130561Sobrien{
2478130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2479130561Sobrien  char ab[20];
2480130561Sobrien
2481130561Sobrien  indent (info);
2482130561Sobrien  print_vma (val, ab, FALSE, FALSE);
2483130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n",
2484130561Sobrien	   name, info->filename, ab);
2485130561Sobrien  return TRUE;
2486130561Sobrien}
2487130561Sobrien
2488130561Sobrien/* Output a floating point constant.  */
2489130561Sobrien
2490130561Sobrienstatic bfd_boolean
2491130561Sobrientg_float_constant (void *p, const char *name, double val)
2492130561Sobrien{
2493130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2494130561Sobrien
2495130561Sobrien  indent (info);
2496130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n",
2497130561Sobrien	   name, info->filename, val);
2498130561Sobrien  return TRUE;
2499130561Sobrien}
2500130561Sobrien
2501130561Sobrien/* Output a typed constant.  */
2502130561Sobrien
2503130561Sobrienstatic bfd_boolean
2504130561Sobrientg_typed_constant (void *p, const char *name, bfd_vma val)
2505130561Sobrien{
2506130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2507130561Sobrien  char *t;
2508130561Sobrien  char ab[20];
2509130561Sobrien
2510130561Sobrien  t = pop_type (info);
2511130561Sobrien  if (t == NULL)
2512130561Sobrien    return FALSE;
2513130561Sobrien
2514130561Sobrien  indent (info);
2515130561Sobrien  print_vma (val, ab, FALSE, FALSE);
2516130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n",
2517130561Sobrien	   name, info->filename, t, ab);
2518130561Sobrien
2519130561Sobrien  free (t);
2520130561Sobrien
2521130561Sobrien  return TRUE;
2522130561Sobrien}
2523130561Sobrien
2524130561Sobrien/* Output a variable.  */
2525130561Sobrien
2526130561Sobrienstatic bfd_boolean
2527130561Sobrientg_variable (void *p, const char *name, enum debug_var_kind kind,
2528130561Sobrien	     bfd_vma val ATTRIBUTE_UNUSED)
2529130561Sobrien{
2530130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2531130561Sobrien  char *t;
2532130561Sobrien  const char *dname, *from_class;
2533130561Sobrien
2534130561Sobrien  t = pop_type (info);
2535130561Sobrien  if (t == NULL)
2536130561Sobrien    return FALSE;
2537130561Sobrien
2538130561Sobrien  dname = name;
2539130561Sobrien  if (info->demangler)
2540130561Sobrien    {
2541130561Sobrien      dname = info->demangler (info->abfd, name);
2542130561Sobrien      if (strcmp (name, dname) == 0)
2543130561Sobrien	{
2544130561Sobrien	  free ((char *) dname);
2545130561Sobrien	  dname = name;
2546130561Sobrien	}
2547130561Sobrien    }
2548130561Sobrien
2549130561Sobrien  if (dname != name)
2550130561Sobrien    {
2551130561Sobrien      char *sep;
2552130561Sobrien      sep = strstr (dname, "::");
2553130561Sobrien      if (sep)
2554130561Sobrien	{
2555130561Sobrien	  *sep = 0;
2556130561Sobrien	  name = sep + 2;
2557130561Sobrien	  from_class = dname;
2558130561Sobrien	}
2559130561Sobrien      else
2560130561Sobrien	{
2561130561Sobrien	  /* Obscure types as vts and type_info nodes.  */
2562130561Sobrien	  name = dname;
2563130561Sobrien	  from_class = NULL;
2564130561Sobrien	}
2565130561Sobrien    }
2566130561Sobrien  else
2567130561Sobrien    from_class = NULL;
2568130561Sobrien
2569130561Sobrien  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t);
2570130561Sobrien
2571130561Sobrien  switch (kind)
2572130561Sobrien    {
2573130561Sobrien    case DEBUG_STATIC:
2574130561Sobrien    case DEBUG_LOCAL_STATIC:
2575130561Sobrien      fprintf (info->f, "\tfile:");
2576130561Sobrien      break;
2577130561Sobrien    case DEBUG_REGISTER:
2578130561Sobrien      fprintf (info->f, "\tregister:");
2579130561Sobrien      break;
2580130561Sobrien    default:
2581130561Sobrien      break;
2582130561Sobrien    }
2583130561Sobrien
2584130561Sobrien  if (from_class)
2585130561Sobrien    {
2586130561Sobrien      fprintf (info->f, "\tclass:%s",from_class);
2587130561Sobrien      free ((char *) dname);
2588130561Sobrien    }
2589130561Sobrien
2590130561Sobrien  fprintf (info->f, "\n");
2591130561Sobrien
2592130561Sobrien  free (t);
2593130561Sobrien
2594130561Sobrien  return TRUE;
2595130561Sobrien}
2596130561Sobrien
2597130561Sobrien/* Start outputting a function.  */
2598130561Sobrien
2599130561Sobrienstatic bfd_boolean
2600130561Sobrientg_start_function (void *p, const char *name, bfd_boolean global)
2601130561Sobrien{
2602130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2603130561Sobrien  const char *dname;
2604130561Sobrien
2605130561Sobrien  if (! global)
2606130561Sobrien    info->stack->flavor = "static";
2607130561Sobrien  else
2608130561Sobrien    info->stack->flavor = NULL;
2609130561Sobrien
2610130561Sobrien  dname = name;
2611130561Sobrien  if (info->demangler)
2612130561Sobrien    {
2613130561Sobrien      dname = info->demangler (info->abfd, name);
2614130561Sobrien      if (strcmp (name, dname) == 0)
2615130561Sobrien	{
2616130561Sobrien	  free ((char *) dname);
2617130561Sobrien	  dname = name;
2618130561Sobrien	}
2619130561Sobrien    }
2620130561Sobrien
2621130561Sobrien  if (! substitute_type (info, dname))
2622130561Sobrien    return FALSE;
2623130561Sobrien
2624130561Sobrien  if (dname != name)
2625130561Sobrien    {
2626130561Sobrien      char *sep;
2627130561Sobrien      sep = strstr (dname, "::");
2628130561Sobrien      if (sep)
2629130561Sobrien	{
2630130561Sobrien	  info->stack->method = dname;
2631130561Sobrien	  *sep = 0;
2632130561Sobrien	  name = sep + 2;
2633130561Sobrien	}
2634130561Sobrien      else
2635130561Sobrien	{
2636130561Sobrien	  info->stack->method = "";
2637130561Sobrien	  name = dname;
2638130561Sobrien	}
2639130561Sobrien      sep = strchr (name, '(');
2640130561Sobrien      if (sep)
2641130561Sobrien	*sep = 0;
2642130561Sobrien      /* Obscure functions as type_info function.  */
2643130561Sobrien    }
2644130561Sobrien  else
2645130561Sobrien    info->stack->method = NULL;
2646130561Sobrien
2647130561Sobrien  info->stack->parents = strdup (name);
2648130561Sobrien
2649130561Sobrien  if (! info->stack->method && ! append_type (info, "("))
2650130561Sobrien    return FALSE;
2651130561Sobrien
2652130561Sobrien  info->parameter = 1;
2653130561Sobrien
2654130561Sobrien  return TRUE;
2655130561Sobrien}
2656130561Sobrien
2657130561Sobrien/* Output a function parameter.  */
2658130561Sobrien
2659130561Sobrienstatic bfd_boolean
2660130561Sobrientg_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
2661130561Sobrien		       bfd_vma val ATTRIBUTE_UNUSED)
2662130561Sobrien{
2663130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2664130561Sobrien  char *t;
2665130561Sobrien
2666130561Sobrien  if (kind == DEBUG_PARM_REFERENCE
2667130561Sobrien      || kind == DEBUG_PARM_REF_REG)
2668130561Sobrien    {
2669130561Sobrien      if (! pr_reference_type (p))
2670130561Sobrien	return FALSE;
2671130561Sobrien    }
2672130561Sobrien
2673130561Sobrien  if (! substitute_type (info, name))
2674130561Sobrien    return FALSE;
2675130561Sobrien
2676130561Sobrien  t = pop_type (info);
2677130561Sobrien  if (t == NULL)
2678130561Sobrien    return FALSE;
2679130561Sobrien
2680130561Sobrien  if (! info->stack->method)
2681130561Sobrien    {
2682130561Sobrien      if (info->parameter != 1 && ! append_type (info, ", "))
2683130561Sobrien	return FALSE;
2684130561Sobrien
2685130561Sobrien      if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
2686130561Sobrien	if (! append_type (info, "register "))
2687130561Sobrien	  return FALSE;
2688130561Sobrien
2689130561Sobrien      if (! append_type (info, t))
2690130561Sobrien	return FALSE;
2691130561Sobrien    }
2692130561Sobrien
2693130561Sobrien  free (t);
2694130561Sobrien
2695130561Sobrien  ++info->parameter;
2696130561Sobrien
2697130561Sobrien  return TRUE;
2698130561Sobrien}
2699130561Sobrien
2700130561Sobrien/* Start writing out a block.  */
2701130561Sobrien
2702130561Sobrienstatic bfd_boolean
2703130561Sobrientg_start_block (void *p, bfd_vma addr)
2704130561Sobrien{
2705130561Sobrien  struct pr_handle *info = (struct pr_handle *) p;
2706130561Sobrien  char ab[20], kind, *partof;
2707130561Sobrien  char *t;
2708130561Sobrien  bfd_boolean local;
2709130561Sobrien
2710130561Sobrien  if (info->parameter > 0)
2711130561Sobrien    {
2712130561Sobrien      info->parameter = 0;
2713130561Sobrien
2714130561Sobrien      /* Delayed name.  */
2715130561Sobrien      fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
2716130561Sobrien      free (info->stack->parents);
2717130561Sobrien
2718130561Sobrien      print_vma (addr, ab, TRUE, TRUE);
2719130561Sobrien      translate_addresses (info->abfd, ab, info->f, info->syms);
2720130561Sobrien      local = info->stack->flavor != NULL;
2721130561Sobrien      if (info->stack->method && *info->stack->method)
2722130561Sobrien	{
2723130561Sobrien	  kind = 'm';
2724130561Sobrien	  partof = (char *) info->stack->method;
2725130561Sobrien	}
2726130561Sobrien      else
2727130561Sobrien	{
2728130561Sobrien	  kind = 'f';
2729130561Sobrien	  partof = NULL;
2730130561Sobrien	  if (! info->stack->method && ! append_type (info, ")"))
2731130561Sobrien	    return FALSE;
2732130561Sobrien	}
2733130561Sobrien      t = pop_type (info);
2734130561Sobrien      if (t == NULL)
2735130561Sobrien	return FALSE;
2736130561Sobrien      fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t);
2737130561Sobrien      if (local)
2738130561Sobrien	fputs ("\tfile:", info->f);
2739130561Sobrien      if (partof)
2740130561Sobrien	{
2741130561Sobrien	  fprintf (info->f, "\tclass:%s", partof);
2742130561Sobrien	  free (partof);
2743130561Sobrien	}
2744130561Sobrien      fputc ('\n', info->f);
2745130561Sobrien    }
2746130561Sobrien
2747130561Sobrien  return TRUE;
2748130561Sobrien}
2749130561Sobrien
2750130561Sobrien/* Write out line number information.  */
2751130561Sobrien
2752130561Sobrienstatic bfd_boolean
2753130561Sobrientg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED,
2754130561Sobrien	   unsigned long lineno ATTRIBUTE_UNUSED,
2755130561Sobrien	   bfd_vma addr ATTRIBUTE_UNUSED)
2756130561Sobrien{
2757130561Sobrien  return TRUE;
2758130561Sobrien}
2759130561Sobrien
2760130561Sobrien/* Finish writing out a block.  */
2761130561Sobrien
2762130561Sobrienstatic bfd_boolean
2763130561Sobrientg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED)
2764130561Sobrien{
2765130561Sobrien  return TRUE;
2766130561Sobrien}
2767130561Sobrien
2768130561Sobrien/* Convert the visibility value into a human readable name.  */
2769130561Sobrien
2770130561Sobrienstatic const char *
2771130561Sobrienvisibility_name (enum debug_visibility visibility)
2772130561Sobrien{
2773130561Sobrien  const char *s;
2774130561Sobrien
2775130561Sobrien  switch (visibility)
2776130561Sobrien    {
2777130561Sobrien    case DEBUG_VISIBILITY_PUBLIC:
2778130561Sobrien      s = "public";
2779130561Sobrien      break;
2780130561Sobrien    case DEBUG_VISIBILITY_PRIVATE:
2781130561Sobrien      s = "private";
2782130561Sobrien      break;
2783130561Sobrien    case DEBUG_VISIBILITY_PROTECTED:
2784130561Sobrien      s = "protected";
2785130561Sobrien      break;
2786130561Sobrien    case DEBUG_VISIBILITY_IGNORE:
2787130561Sobrien      s = "/* ignore */";
2788130561Sobrien      break;
2789130561Sobrien    default:
2790130561Sobrien      abort ();
2791130561Sobrien      return FALSE;
2792130561Sobrien    }
2793130561Sobrien  return s;
2794130561Sobrien}
2795