OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [prdbg.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* prdbg.c -- Print out generic debugging information.
/* prdbg.c -- Print out generic debugging information.
   Copyright 1995, 1996, 1999, 2002, 2003, 2004, 2006, 2007, 2008
   Copyright 1995, 1996, 1999, 2002, 2003, 2004, 2006, 2007, 2008
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Ian Lance Taylor <ian@cygnus.com>.
   Written by Ian Lance Taylor <ian@cygnus.com>.
   Tags style generation written by Salvador E. Tropea <set@computer.org>.
   Tags style generation written by Salvador E. Tropea <set@computer.org>.
 
 
   This file is part of GNU Binutils.
   This file is part of GNU Binutils.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
/* This file prints out the generic debugging information, by
/* This file prints out the generic debugging information, by
   supplying a set of routines to debug_write.  */
   supplying a set of routines to debug_write.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include <assert.h>
#include <assert.h>
#include "bfd.h"
#include "bfd.h"
#include "libiberty.h"
#include "libiberty.h"
#include "demangle.h"
#include "demangle.h"
#include "debug.h"
#include "debug.h"
#include "budbg.h"
#include "budbg.h"
 
 
/* This is the structure we use as a handle for these routines.  */
/* This is the structure we use as a handle for these routines.  */
 
 
struct pr_handle
struct pr_handle
{
{
  /* File to print information to.  */
  /* File to print information to.  */
  FILE *f;
  FILE *f;
  /* Current indentation level.  */
  /* Current indentation level.  */
  unsigned int indent;
  unsigned int indent;
  /* Type stack.  */
  /* Type stack.  */
  struct pr_stack *stack;
  struct pr_stack *stack;
  /* Parameter number we are about to output.  */
  /* Parameter number we are about to output.  */
  int parameter;
  int parameter;
  /* The following are used only by the tags code (tg_).  */
  /* The following are used only by the tags code (tg_).  */
  /* Name of the file we are using.  */
  /* Name of the file we are using.  */
  char *filename;
  char *filename;
  /* The BFD.  */
  /* The BFD.  */
  bfd *abfd;
  bfd *abfd;
  /* The symbols table for this BFD.  */
  /* The symbols table for this BFD.  */
  asymbol **syms;
  asymbol **syms;
  /* Pointer to a function to demangle symbols.  */
  /* Pointer to a function to demangle symbols.  */
  char *(*demangler) (bfd *, const char *, int);
  char *(*demangler) (bfd *, const char *, int);
};
};
 
 
/* The type stack.  */
/* The type stack.  */
 
 
struct pr_stack
struct pr_stack
{
{
  /* Next element on the stack.  */
  /* Next element on the stack.  */
  struct pr_stack *next;
  struct pr_stack *next;
  /* This element.  */
  /* This element.  */
  char *type;
  char *type;
  /* Current visibility of fields if this is a class.  */
  /* Current visibility of fields if this is a class.  */
  enum debug_visibility visibility;
  enum debug_visibility visibility;
  /* Name of the current method we are handling.  */
  /* Name of the current method we are handling.  */
  const char *method;
  const char *method;
  /* The following are used only by the tags code (tg_).  */
  /* The following are used only by the tags code (tg_).  */
  /* Type for the container (struct, union, class, union class).  */
  /* Type for the container (struct, union, class, union class).  */
  const char *flavor;
  const char *flavor;
  /* A comma separated list of parent classes.  */
  /* A comma separated list of parent classes.  */
  char *parents;
  char *parents;
  /* How many parents contains parents.  */
  /* How many parents contains parents.  */
  int num_parents;
  int num_parents;
};
};
 
 
static void indent (struct pr_handle *);
static void indent (struct pr_handle *);
static bfd_boolean push_type (struct pr_handle *, const char *);
static bfd_boolean push_type (struct pr_handle *, const char *);
static bfd_boolean prepend_type (struct pr_handle *, const char *);
static bfd_boolean prepend_type (struct pr_handle *, const char *);
static bfd_boolean append_type (struct pr_handle *, const char *);
static bfd_boolean append_type (struct pr_handle *, const char *);
static bfd_boolean substitute_type (struct pr_handle *, const char *);
static bfd_boolean substitute_type (struct pr_handle *, const char *);
static bfd_boolean indent_type (struct pr_handle *);
static bfd_boolean indent_type (struct pr_handle *);
static char *pop_type (struct pr_handle *);
static char *pop_type (struct pr_handle *);
static void print_vma (bfd_vma, char *, bfd_boolean, bfd_boolean);
static void print_vma (bfd_vma, char *, bfd_boolean, bfd_boolean);
static bfd_boolean pr_fix_visibility
static bfd_boolean pr_fix_visibility
  (struct pr_handle *, enum debug_visibility);
  (struct pr_handle *, enum debug_visibility);
static bfd_boolean pr_start_compilation_unit (void *, const char *);
static bfd_boolean pr_start_compilation_unit (void *, const char *);
static bfd_boolean pr_start_source (void *, const char *);
static bfd_boolean pr_start_source (void *, const char *);
static bfd_boolean pr_empty_type (void *);
static bfd_boolean pr_empty_type (void *);
static bfd_boolean pr_void_type (void *);
static bfd_boolean pr_void_type (void *);
static bfd_boolean pr_int_type (void *, unsigned int, bfd_boolean);
static bfd_boolean pr_int_type (void *, unsigned int, bfd_boolean);
static bfd_boolean pr_float_type (void *, unsigned int);
static bfd_boolean pr_float_type (void *, unsigned int);
static bfd_boolean pr_complex_type (void *, unsigned int);
static bfd_boolean pr_complex_type (void *, unsigned int);
static bfd_boolean pr_bool_type (void *, unsigned int);
static bfd_boolean pr_bool_type (void *, unsigned int);
static bfd_boolean pr_enum_type
static bfd_boolean pr_enum_type
  (void *, const char *, const char **, bfd_signed_vma *);
  (void *, const char *, const char **, bfd_signed_vma *);
static bfd_boolean pr_pointer_type (void *);
static bfd_boolean pr_pointer_type (void *);
static bfd_boolean pr_function_type (void *, int, bfd_boolean);
static bfd_boolean pr_function_type (void *, int, bfd_boolean);
static bfd_boolean pr_reference_type (void *);
static bfd_boolean pr_reference_type (void *);
static bfd_boolean pr_range_type (void *, bfd_signed_vma, bfd_signed_vma);
static bfd_boolean pr_range_type (void *, bfd_signed_vma, bfd_signed_vma);
static bfd_boolean pr_array_type
static bfd_boolean pr_array_type
  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
static bfd_boolean pr_set_type (void *, bfd_boolean);
static bfd_boolean pr_set_type (void *, bfd_boolean);
static bfd_boolean pr_offset_type (void *);
static bfd_boolean pr_offset_type (void *);
static bfd_boolean pr_method_type (void *, bfd_boolean, int, bfd_boolean);
static bfd_boolean pr_method_type (void *, bfd_boolean, int, bfd_boolean);
static bfd_boolean pr_const_type (void *);
static bfd_boolean pr_const_type (void *);
static bfd_boolean pr_volatile_type (void *);
static bfd_boolean pr_volatile_type (void *);
static bfd_boolean pr_start_struct_type
static bfd_boolean pr_start_struct_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
static bfd_boolean pr_struct_field
static bfd_boolean pr_struct_field
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
static bfd_boolean pr_end_struct_type (void *);
static bfd_boolean pr_end_struct_type (void *);
static bfd_boolean pr_start_class_type
static bfd_boolean pr_start_class_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int,
  (void *, const char *, unsigned int, bfd_boolean, unsigned int,
   bfd_boolean, bfd_boolean);
   bfd_boolean, bfd_boolean);
static bfd_boolean pr_class_static_member
static bfd_boolean pr_class_static_member
  (void *, const char *, const char *, enum debug_visibility);
  (void *, const char *, const char *, enum debug_visibility);
static bfd_boolean pr_class_baseclass
static bfd_boolean pr_class_baseclass
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
static bfd_boolean pr_class_start_method (void *, const char *);
static bfd_boolean pr_class_start_method (void *, const char *);
static bfd_boolean pr_class_method_variant
static bfd_boolean pr_class_method_variant
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
   bfd_vma, bfd_boolean);
   bfd_vma, bfd_boolean);
static bfd_boolean pr_class_static_method_variant
static bfd_boolean pr_class_static_method_variant
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
static bfd_boolean pr_class_end_method (void *);
static bfd_boolean pr_class_end_method (void *);
static bfd_boolean pr_end_class_type (void *);
static bfd_boolean pr_end_class_type (void *);
static bfd_boolean pr_typedef_type (void *, const char *);
static bfd_boolean pr_typedef_type (void *, const char *);
static bfd_boolean pr_tag_type
static bfd_boolean pr_tag_type
  (void *, const char *, unsigned int, enum debug_type_kind);
  (void *, const char *, unsigned int, enum debug_type_kind);
static bfd_boolean pr_typdef (void *, const char *);
static bfd_boolean pr_typdef (void *, const char *);
static bfd_boolean pr_tag (void *, const char *);
static bfd_boolean pr_tag (void *, const char *);
static bfd_boolean pr_int_constant (void *, const char *, bfd_vma);
static bfd_boolean pr_int_constant (void *, const char *, bfd_vma);
static bfd_boolean pr_float_constant (void *, const char *, double);
static bfd_boolean pr_float_constant (void *, const char *, double);
static bfd_boolean pr_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean pr_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean pr_variable
static bfd_boolean pr_variable
  (void *, const char *, enum debug_var_kind, bfd_vma);
  (void *, const char *, enum debug_var_kind, bfd_vma);
static bfd_boolean pr_start_function (void *, const char *, bfd_boolean);
static bfd_boolean pr_start_function (void *, const char *, bfd_boolean);
static bfd_boolean pr_function_parameter
static bfd_boolean pr_function_parameter
  (void *, const char *, enum debug_parm_kind, bfd_vma);
  (void *, const char *, enum debug_parm_kind, bfd_vma);
static bfd_boolean pr_start_block (void *, bfd_vma);
static bfd_boolean pr_start_block (void *, bfd_vma);
static bfd_boolean pr_end_block (void *, bfd_vma);
static bfd_boolean pr_end_block (void *, bfd_vma);
static bfd_boolean pr_end_function (void *);
static bfd_boolean pr_end_function (void *);
static bfd_boolean pr_lineno (void *, const char *, unsigned long, bfd_vma);
static bfd_boolean pr_lineno (void *, const char *, unsigned long, bfd_vma);
static bfd_boolean append_parent (struct pr_handle *, const char *);
static bfd_boolean append_parent (struct pr_handle *, const char *);
/* Only used by tg_ code.  */
/* Only used by tg_ code.  */
static bfd_boolean tg_fix_visibility
static bfd_boolean tg_fix_visibility
  (struct pr_handle *, enum debug_visibility);
  (struct pr_handle *, enum debug_visibility);
static void find_address_in_section (bfd *, asection *, void *);
static void find_address_in_section (bfd *, asection *, void *);
static void translate_addresses (bfd *, char *, FILE *, asymbol **);
static void translate_addresses (bfd *, char *, FILE *, asymbol **);
static const char *visibility_name (enum debug_visibility);
static const char *visibility_name (enum debug_visibility);
/* Tags style replacements.  */
/* Tags style replacements.  */
static bfd_boolean tg_start_compilation_unit (void *, const char *);
static bfd_boolean tg_start_compilation_unit (void *, const char *);
static bfd_boolean tg_start_source (void *, const char *);
static bfd_boolean tg_start_source (void *, const char *);
static bfd_boolean tg_enum_type
static bfd_boolean tg_enum_type
  (void *, const char *, const char **, bfd_signed_vma *);
  (void *, const char *, const char **, bfd_signed_vma *);
static bfd_boolean tg_start_struct_type
static bfd_boolean tg_start_struct_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
static bfd_boolean pr_struct_field
static bfd_boolean pr_struct_field
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
static bfd_boolean tg_struct_field
static bfd_boolean tg_struct_field
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
static bfd_boolean tg_struct_field
static bfd_boolean tg_struct_field
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
  (void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
static bfd_boolean tg_end_struct_type (void *);
static bfd_boolean tg_end_struct_type (void *);
static bfd_boolean tg_start_class_type
static bfd_boolean tg_start_class_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, bfd_boolean);
  (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, bfd_boolean);
static bfd_boolean tg_class_static_member
static bfd_boolean tg_class_static_member
  (void *, const char *, const char *, enum debug_visibility);
  (void *, const char *, const char *, enum debug_visibility);
static bfd_boolean tg_class_baseclass
static bfd_boolean tg_class_baseclass
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
static bfd_boolean tg_class_method_variant
static bfd_boolean tg_class_method_variant
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
static bfd_boolean tg_class_static_method_variant
static bfd_boolean tg_class_static_method_variant
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
  (void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
static bfd_boolean tg_end_class_type (void *);
static bfd_boolean tg_end_class_type (void *);
static bfd_boolean tg_tag_type
static bfd_boolean tg_tag_type
  (void *, const char *, unsigned int, enum debug_type_kind);
  (void *, const char *, unsigned int, enum debug_type_kind);
static bfd_boolean tg_typdef (void *, const char *);
static bfd_boolean tg_typdef (void *, const char *);
static bfd_boolean tg_tag (void *, const char *);
static bfd_boolean tg_tag (void *, const char *);
static bfd_boolean tg_int_constant (void *, const char *, bfd_vma);
static bfd_boolean tg_int_constant (void *, const char *, bfd_vma);
static bfd_boolean tg_float_constant (void *, const char *, double);
static bfd_boolean tg_float_constant (void *, const char *, double);
static bfd_boolean tg_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean tg_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean tg_variable
static bfd_boolean tg_variable
  (void *, const char *, enum debug_var_kind, bfd_vma);
  (void *, const char *, enum debug_var_kind, bfd_vma);
static bfd_boolean tg_start_function (void *, const char *, bfd_boolean);
static bfd_boolean tg_start_function (void *, const char *, bfd_boolean);
static bfd_boolean tg_function_parameter
static bfd_boolean tg_function_parameter
  (void *, const char *, enum debug_parm_kind, bfd_vma);
  (void *, const char *, enum debug_parm_kind, bfd_vma);
static bfd_boolean tg_start_block (void *, bfd_vma);
static bfd_boolean tg_start_block (void *, bfd_vma);
static bfd_boolean tg_end_block (void *, bfd_vma);
static bfd_boolean tg_end_block (void *, bfd_vma);
static bfd_boolean tg_lineno (void *, const char *, unsigned long, bfd_vma);
static bfd_boolean tg_lineno (void *, const char *, unsigned long, bfd_vma);


static const struct debug_write_fns pr_fns =
static const struct debug_write_fns pr_fns =
{
{
  pr_start_compilation_unit,
  pr_start_compilation_unit,
  pr_start_source,
  pr_start_source,
  pr_empty_type,
  pr_empty_type,
  pr_void_type,
  pr_void_type,
  pr_int_type,
  pr_int_type,
  pr_float_type,
  pr_float_type,
  pr_complex_type,
  pr_complex_type,
  pr_bool_type,
  pr_bool_type,
  pr_enum_type,
  pr_enum_type,
  pr_pointer_type,
  pr_pointer_type,
  pr_function_type,
  pr_function_type,
  pr_reference_type,
  pr_reference_type,
  pr_range_type,
  pr_range_type,
  pr_array_type,
  pr_array_type,
  pr_set_type,
  pr_set_type,
  pr_offset_type,
  pr_offset_type,
  pr_method_type,
  pr_method_type,
  pr_const_type,
  pr_const_type,
  pr_volatile_type,
  pr_volatile_type,
  pr_start_struct_type,
  pr_start_struct_type,
  pr_struct_field,
  pr_struct_field,
  pr_end_struct_type,
  pr_end_struct_type,
  pr_start_class_type,
  pr_start_class_type,
  pr_class_static_member,
  pr_class_static_member,
  pr_class_baseclass,
  pr_class_baseclass,
  pr_class_start_method,
  pr_class_start_method,
  pr_class_method_variant,
  pr_class_method_variant,
  pr_class_static_method_variant,
  pr_class_static_method_variant,
  pr_class_end_method,
  pr_class_end_method,
  pr_end_class_type,
  pr_end_class_type,
  pr_typedef_type,
  pr_typedef_type,
  pr_tag_type,
  pr_tag_type,
  pr_typdef,
  pr_typdef,
  pr_tag,
  pr_tag,
  pr_int_constant,
  pr_int_constant,
  pr_float_constant,
  pr_float_constant,
  pr_typed_constant,
  pr_typed_constant,
  pr_variable,
  pr_variable,
  pr_start_function,
  pr_start_function,
  pr_function_parameter,
  pr_function_parameter,
  pr_start_block,
  pr_start_block,
  pr_end_block,
  pr_end_block,
  pr_end_function,
  pr_end_function,
  pr_lineno
  pr_lineno
};
};


static const struct debug_write_fns tg_fns =
static const struct debug_write_fns tg_fns =
{
{
  tg_start_compilation_unit,
  tg_start_compilation_unit,
  tg_start_source,
  tg_start_source,
  pr_empty_type,                /* Same, push_type.  */
  pr_empty_type,                /* Same, push_type.  */
  pr_void_type,                 /* Same, push_type.  */
  pr_void_type,                 /* Same, push_type.  */
  pr_int_type,                  /* Same, push_type.  */
  pr_int_type,                  /* Same, push_type.  */
  pr_float_type,                /* Same, push_type.  */
  pr_float_type,                /* Same, push_type.  */
  pr_complex_type,              /* Same, push_type.  */
  pr_complex_type,              /* Same, push_type.  */
  pr_bool_type,                 /* Same, push_type.  */
  pr_bool_type,                 /* Same, push_type.  */
  tg_enum_type,
  tg_enum_type,
  pr_pointer_type,              /* Same, changes to pointer.  */
  pr_pointer_type,              /* Same, changes to pointer.  */
  pr_function_type,             /* Same, push_type.  */
  pr_function_type,             /* Same, push_type.  */
  pr_reference_type,            /* Same, changes to reference.  */
  pr_reference_type,            /* Same, changes to reference.  */
  pr_range_type,                /* FIXME: What's that?.  */
  pr_range_type,                /* FIXME: What's that?.  */
  pr_array_type,                /* Same, push_type.  */
  pr_array_type,                /* Same, push_type.  */
  pr_set_type,                  /* FIXME: What's that?.  */
  pr_set_type,                  /* FIXME: What's that?.  */
  pr_offset_type,               /* FIXME: What's that?.  */
  pr_offset_type,               /* FIXME: What's that?.  */
  pr_method_type,               /* Same.  */
  pr_method_type,               /* Same.  */
  pr_const_type,                /* Same, changes to const.  */
  pr_const_type,                /* Same, changes to const.  */
  pr_volatile_type,             /* Same, changes to volatile.  */
  pr_volatile_type,             /* Same, changes to volatile.  */
  tg_start_struct_type,
  tg_start_struct_type,
  tg_struct_field,
  tg_struct_field,
  tg_end_struct_type,
  tg_end_struct_type,
  tg_start_class_type,
  tg_start_class_type,
  tg_class_static_member,
  tg_class_static_member,
  tg_class_baseclass,
  tg_class_baseclass,
  pr_class_start_method,        /* Same, remembers that's a method.  */
  pr_class_start_method,        /* Same, remembers that's a method.  */
  tg_class_method_variant,
  tg_class_method_variant,
  tg_class_static_method_variant,
  tg_class_static_method_variant,
  pr_class_end_method,          /* Same, forgets that's a method.  */
  pr_class_end_method,          /* Same, forgets that's a method.  */
  tg_end_class_type,
  tg_end_class_type,
  pr_typedef_type,              /* Same, just push type.  */
  pr_typedef_type,              /* Same, just push type.  */
  tg_tag_type,
  tg_tag_type,
  tg_typdef,
  tg_typdef,
  tg_tag,
  tg_tag,
  tg_int_constant,              /* Untested.  */
  tg_int_constant,              /* Untested.  */
  tg_float_constant,            /* Untested.  */
  tg_float_constant,            /* Untested.  */
  tg_typed_constant,            /* Untested.  */
  tg_typed_constant,            /* Untested.  */
  tg_variable,
  tg_variable,
  tg_start_function,
  tg_start_function,
  tg_function_parameter,
  tg_function_parameter,
  tg_start_block,
  tg_start_block,
  tg_end_block,
  tg_end_block,
  pr_end_function,              /* Same, does nothing.  */
  pr_end_function,              /* Same, does nothing.  */
  tg_lineno
  tg_lineno
};
};


/* Print out the generic debugging information recorded in dhandle.  */
/* Print out the generic debugging information recorded in dhandle.  */
 
 
bfd_boolean
bfd_boolean
print_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms,
print_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms,
                      void *demangler, bfd_boolean as_tags)
                      void *demangler, bfd_boolean as_tags)
{
{
  struct pr_handle info;
  struct pr_handle info;
 
 
  info.f = f;
  info.f = f;
  info.indent = 0;
  info.indent = 0;
  info.stack = NULL;
  info.stack = NULL;
  info.parameter = 0;
  info.parameter = 0;
  info.filename = NULL;
  info.filename = NULL;
  info.abfd = abfd;
  info.abfd = abfd;
  info.syms = syms;
  info.syms = syms;
  info.demangler = demangler;
  info.demangler = demangler;
 
 
  if (as_tags)
  if (as_tags)
    {
    {
      fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f);
      fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f);
      fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f);
      fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f);
      fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f);
      fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f);
      fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f);
      fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f);
    }
    }
 
 
  return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info)
  return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info)
    : debug_write (dhandle, &pr_fns, (void *) & info);
    : debug_write (dhandle, &pr_fns, (void *) & info);
}
}


/* Indent to the current indentation level.  */
/* Indent to the current indentation level.  */
 
 
static void
static void
indent (struct pr_handle *info)
indent (struct pr_handle *info)
{
{
  unsigned int i;
  unsigned int i;
 
 
  for (i = 0; i < info->indent; i++)
  for (i = 0; i < info->indent; i++)
    putc (' ', info->f);
    putc (' ', info->f);
}
}
 
 
/* Push a type on the type stack.  */
/* Push a type on the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
push_type (struct pr_handle *info, const char *type)
push_type (struct pr_handle *info, const char *type)
{
{
  struct pr_stack *n;
  struct pr_stack *n;
 
 
  if (type == NULL)
  if (type == NULL)
    return FALSE;
    return FALSE;
 
 
  n = (struct pr_stack *) xmalloc (sizeof *n);
  n = (struct pr_stack *) xmalloc (sizeof *n);
  memset (n, 0, sizeof *n);
  memset (n, 0, sizeof *n);
 
 
  n->type = xstrdup (type);
  n->type = xstrdup (type);
  n->visibility = DEBUG_VISIBILITY_IGNORE;
  n->visibility = DEBUG_VISIBILITY_IGNORE;
  n->method = NULL;
  n->method = NULL;
  n->next = info->stack;
  n->next = info->stack;
  info->stack = n;
  info->stack = n;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Prepend a string onto the type on the top of the type stack.  */
/* Prepend a string onto the type on the top of the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
prepend_type (struct pr_handle *info, const char *s)
prepend_type (struct pr_handle *info, const char *s)
{
{
  char *n;
  char *n;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
  sprintf (n, "%s%s", s, info->stack->type);
  sprintf (n, "%s%s", s, info->stack->type);
  free (info->stack->type);
  free (info->stack->type);
  info->stack->type = n;
  info->stack->type = n;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Append a string to the type on the top of the type stack.  */
/* Append a string to the type on the top of the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
append_type (struct pr_handle *info, const char *s)
append_type (struct pr_handle *info, const char *s)
{
{
  unsigned int len;
  unsigned int len;
 
 
  if (s == NULL)
  if (s == NULL)
    return FALSE;
    return FALSE;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  len = strlen (info->stack->type);
  len = strlen (info->stack->type);
  info->stack->type = (char *) xrealloc (info->stack->type,
  info->stack->type = (char *) xrealloc (info->stack->type,
                                         len + strlen (s) + 1);
                                         len + strlen (s) + 1);
  strcpy (info->stack->type + len, s);
  strcpy (info->stack->type + len, s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Append a string to the parents on the top of the type stack.  */
/* Append a string to the parents on the top of the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
append_parent (struct pr_handle *info, const char *s)
append_parent (struct pr_handle *info, const char *s)
{
{
  unsigned int len;
  unsigned int len;
 
 
  if (s == NULL)
  if (s == NULL)
    return FALSE;
    return FALSE;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  len = info->stack->parents ? strlen (info->stack->parents) : 0;
  len = info->stack->parents ? strlen (info->stack->parents) : 0;
  info->stack->parents = (char *) xrealloc (info->stack->parents,
  info->stack->parents = (char *) xrealloc (info->stack->parents,
                                            len + strlen (s) + 1);
                                            len + strlen (s) + 1);
  strcpy (info->stack->parents + len, s);
  strcpy (info->stack->parents + len, s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* We use an underscore to indicate where the name should go in a type
/* We use an underscore to indicate where the name should go in a type
   string.  This function substitutes a string for the underscore.  If
   string.  This function substitutes a string for the underscore.  If
   there is no underscore, the name follows the type.  */
   there is no underscore, the name follows the type.  */
 
 
static bfd_boolean
static bfd_boolean
substitute_type (struct pr_handle *info, const char *s)
substitute_type (struct pr_handle *info, const char *s)
{
{
  char *u;
  char *u;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  u = strchr (info->stack->type, '|');
  u = strchr (info->stack->type, '|');
  if (u != NULL)
  if (u != NULL)
    {
    {
      char *n;
      char *n;
 
 
      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
 
 
      memcpy (n, info->stack->type, u - info->stack->type);
      memcpy (n, info->stack->type, u - info->stack->type);
      strcpy (n + (u - info->stack->type), s);
      strcpy (n + (u - info->stack->type), s);
      strcat (n, u + 1);
      strcat (n, u + 1);
 
 
      free (info->stack->type);
      free (info->stack->type);
      info->stack->type = n;
      info->stack->type = n;
 
 
      return TRUE;
      return TRUE;
    }
    }
 
 
  if (strchr (s, '|') != NULL
  if (strchr (s, '|') != NULL
      && (strchr (info->stack->type, '{') != NULL
      && (strchr (info->stack->type, '{') != NULL
          || strchr (info->stack->type, '(') != NULL))
          || strchr (info->stack->type, '(') != NULL))
    {
    {
      if (! prepend_type (info, "(")
      if (! prepend_type (info, "(")
          || ! append_type (info, ")"))
          || ! append_type (info, ")"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (*s == '\0')
  if (*s == '\0')
    return TRUE;
    return TRUE;
 
 
  return (append_type (info, " ")
  return (append_type (info, " ")
          && append_type (info, s));
          && append_type (info, s));
}
}
 
 
/* Indent the type at the top of the stack by appending spaces.  */
/* Indent the type at the top of the stack by appending spaces.  */
 
 
static bfd_boolean
static bfd_boolean
indent_type (struct pr_handle *info)
indent_type (struct pr_handle *info)
{
{
  unsigned int i;
  unsigned int i;
 
 
  for (i = 0; i < info->indent; i++)
  for (i = 0; i < info->indent; i++)
    {
    {
      if (! append_type (info, " "))
      if (! append_type (info, " "))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Pop a type from the type stack.  */
/* Pop a type from the type stack.  */
 
 
static char *
static char *
pop_type (struct pr_handle *info)
pop_type (struct pr_handle *info)
{
{
  struct pr_stack *o;
  struct pr_stack *o;
  char *ret;
  char *ret;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  o = info->stack;
  o = info->stack;
  info->stack = o->next;
  info->stack = o->next;
  ret = o->type;
  ret = o->type;
  free (o);
  free (o);
 
 
  return ret;
  return ret;
}
}
 
 
/* Print a VMA value into a string.  */
/* Print a VMA value into a string.  */
 
 
static void
static void
print_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp)
print_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp)
{
{
  if (sizeof (vma) <= sizeof (unsigned long))
  if (sizeof (vma) <= sizeof (unsigned long))
    {
    {
      if (hexp)
      if (hexp)
        sprintf (buf, "0x%lx", (unsigned long) vma);
        sprintf (buf, "0x%lx", (unsigned long) vma);
      else if (unsignedp)
      else if (unsignedp)
        sprintf (buf, "%lu", (unsigned long) vma);
        sprintf (buf, "%lu", (unsigned long) vma);
      else
      else
        sprintf (buf, "%ld", (long) vma);
        sprintf (buf, "%ld", (long) vma);
    }
    }
#if BFD_HOST_64BIT_LONG_LONG
#if BFD_HOST_64BIT_LONG_LONG
  else if (sizeof (vma) <= sizeof (unsigned long long))
  else if (sizeof (vma) <= sizeof (unsigned long long))
    {
    {
#ifndef __MSVCRT__
#ifndef __MSVCRT__
      if (hexp)
      if (hexp)
        sprintf (buf, "0x%llx", (unsigned long long) vma);
        sprintf (buf, "0x%llx", (unsigned long long) vma);
      else if (unsignedp)
      else if (unsignedp)
        sprintf (buf, "%llu", (unsigned long long) vma);
        sprintf (buf, "%llu", (unsigned long long) vma);
      else
      else
        sprintf (buf, "%lld", (long long) vma);
        sprintf (buf, "%lld", (long long) vma);
#else
#else
      if (hexp)
      if (hexp)
        sprintf (buf, "0x%I64x", (unsigned long long) vma);
        sprintf (buf, "0x%I64x", (unsigned long long) vma);
      else if (unsignedp)
      else if (unsignedp)
        sprintf (buf, "%I64u", (unsigned long long) vma);
        sprintf (buf, "%I64u", (unsigned long long) vma);
      else
      else
        sprintf (buf, "%I64d", (long long) vma);
        sprintf (buf, "%I64d", (long long) vma);
#endif
#endif
    }
    }
#endif
#endif
  else
  else
    {
    {
      buf[0] = '0';
      buf[0] = '0';
      buf[1] = 'x';
      buf[1] = 'x';
      sprintf_vma (buf + 2, vma);
      sprintf_vma (buf + 2, vma);
    }
    }
}
}


/* Start a new compilation unit.  */
/* Start a new compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_compilation_unit (void *p, const char *filename)
pr_start_compilation_unit (void *p, const char *filename)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  assert (info->indent == 0);
  assert (info->indent == 0);
 
 
  fprintf (info->f, "%s:\n", filename);
  fprintf (info->f, "%s:\n", filename);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a source file within a compilation unit.  */
/* Start a source file within a compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_source (void *p, const char *filename)
pr_start_source (void *p, const char *filename)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  assert (info->indent == 0);
  assert (info->indent == 0);
 
 
  fprintf (info->f, " %s:\n", filename);
  fprintf (info->f, " %s:\n", filename);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Push an empty type onto the type stack.  */
/* Push an empty type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_empty_type (void *p)
pr_empty_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  return push_type (info, "<undefined>");
  return push_type (info, "<undefined>");
}
}
 
 
/* Push a void type onto the type stack.  */
/* Push a void type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_void_type (void *p)
pr_void_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  return push_type (info, "void");
  return push_type (info, "void");
}
}
 
 
/* Push an integer type onto the type stack.  */
/* Push an integer type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
pr_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[10];
  char ab[10];
 
 
  sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
  sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
  return push_type (info, ab);
  return push_type (info, ab);
}
}
 
 
/* Push a floating type onto the type stack.  */
/* Push a floating type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_float_type (void *p, unsigned int size)
pr_float_type (void *p, unsigned int size)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[10];
  char ab[10];
 
 
  if (size == 4)
  if (size == 4)
    return push_type (info, "float");
    return push_type (info, "float");
  else if (size == 8)
  else if (size == 8)
    return push_type (info, "double");
    return push_type (info, "double");
 
 
  sprintf (ab, "float%d", size * 8);
  sprintf (ab, "float%d", size * 8);
  return push_type (info, ab);
  return push_type (info, ab);
}
}
 
 
/* Push a complex type onto the type stack.  */
/* Push a complex type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_complex_type (void *p, unsigned int size)
pr_complex_type (void *p, unsigned int size)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  if (! pr_float_type (p, size))
  if (! pr_float_type (p, size))
    return FALSE;
    return FALSE;
 
 
  return prepend_type (info, "complex ");
  return prepend_type (info, "complex ");
}
}
 
 
/* Push a bfd_boolean type onto the type stack.  */
/* Push a bfd_boolean type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_bool_type (void *p, unsigned int size)
pr_bool_type (void *p, unsigned int size)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[10];
  char ab[10];
 
 
  sprintf (ab, "bool%d", size * 8);
  sprintf (ab, "bool%d", size * 8);
 
 
  return push_type (info, ab);
  return push_type (info, ab);
}
}
 
 
/* Push an enum type onto the type stack.  */
/* Push an enum type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
pr_enum_type (void *p, const char *tag, const char **names,
pr_enum_type (void *p, const char *tag, const char **names,
              bfd_signed_vma *values)
              bfd_signed_vma *values)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  unsigned int i;
  unsigned int i;
  bfd_signed_vma val;
  bfd_signed_vma val;
 
 
  if (! push_type (info, "enum "))
  if (! push_type (info, "enum "))
    return FALSE;
    return FALSE;
  if (tag != NULL)
  if (tag != NULL)
    {
    {
      if (! append_type (info, tag)
      if (! append_type (info, tag)
          || ! append_type (info, " "))
          || ! append_type (info, " "))
        return FALSE;
        return FALSE;
    }
    }
  if (! append_type (info, "{ "))
  if (! append_type (info, "{ "))
    return FALSE;
    return FALSE;
 
 
  if (names == NULL)
  if (names == NULL)
    {
    {
      if (! append_type (info, "/* undefined */"))
      if (! append_type (info, "/* undefined */"))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      val = 0;
      val = 0;
      for (i = 0; names[i] != NULL; i++)
      for (i = 0; names[i] != NULL; i++)
        {
        {
          if (i > 0)
          if (i > 0)
            {
            {
              if (! append_type (info, ", "))
              if (! append_type (info, ", "))
                return FALSE;
                return FALSE;
            }
            }
 
 
          if (! append_type (info, names[i]))
          if (! append_type (info, names[i]))
            return FALSE;
            return FALSE;
 
 
          if (values[i] != val)
          if (values[i] != val)
            {
            {
              char ab[20];
              char ab[20];
 
 
              print_vma (values[i], ab, FALSE, FALSE);
              print_vma (values[i], ab, FALSE, FALSE);
              if (! append_type (info, " = ")
              if (! append_type (info, " = ")
                  || ! append_type (info, ab))
                  || ! append_type (info, ab))
                return FALSE;
                return FALSE;
              val = values[i];
              val = values[i];
            }
            }
 
 
          ++val;
          ++val;
        }
        }
    }
    }
 
 
  return append_type (info, " }");
  return append_type (info, " }");
}
}
 
 
/* Turn the top type on the stack into a pointer.  */
/* Turn the top type on the stack into a pointer.  */
 
 
static bfd_boolean
static bfd_boolean
pr_pointer_type (void *p)
pr_pointer_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *s;
  char *s;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  s = strchr (info->stack->type, '|');
  s = strchr (info->stack->type, '|');
  if (s != NULL && s[1] == '[')
  if (s != NULL && s[1] == '[')
    return substitute_type (info, "(*|)");
    return substitute_type (info, "(*|)");
  return substitute_type (info, "*|");
  return substitute_type (info, "*|");
}
}
 
 
/* Turn the top type on the stack into a function returning that type.  */
/* Turn the top type on the stack into a function returning that type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_function_type (void *p, int argcount, bfd_boolean varargs)
pr_function_type (void *p, int argcount, bfd_boolean varargs)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char **arg_types;
  char **arg_types;
  unsigned int len;
  unsigned int len;
  char *s;
  char *s;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  len = 10;
  len = 10;
 
 
  if (argcount <= 0)
  if (argcount <= 0)
    {
    {
      arg_types = NULL;
      arg_types = NULL;
      len += 15;
      len += 15;
    }
    }
  else
  else
    {
    {
      int i;
      int i;
 
 
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
      for (i = argcount - 1; i >= 0; i--)
      for (i = argcount - 1; i >= 0; i--)
        {
        {
          if (! substitute_type (info, ""))
          if (! substitute_type (info, ""))
            return FALSE;
            return FALSE;
          arg_types[i] = pop_type (info);
          arg_types[i] = pop_type (info);
          if (arg_types[i] == NULL)
          if (arg_types[i] == NULL)
            return FALSE;
            return FALSE;
          len += strlen (arg_types[i]) + 2;
          len += strlen (arg_types[i]) + 2;
        }
        }
      if (varargs)
      if (varargs)
        len += 5;
        len += 5;
    }
    }
 
 
  /* Now the return type is on the top of the stack.  */
  /* Now the return type is on the top of the stack.  */
 
 
  s = xmalloc (len);
  s = xmalloc (len);
  LITSTRCPY (s, "(|) (");
  LITSTRCPY (s, "(|) (");
 
 
  if (argcount < 0)
  if (argcount < 0)
    strcat (s, "/* unknown */");
    strcat (s, "/* unknown */");
  else
  else
    {
    {
      int i;
      int i;
 
 
      for (i = 0; i < argcount; i++)
      for (i = 0; i < argcount; i++)
        {
        {
          if (i > 0)
          if (i > 0)
            strcat (s, ", ");
            strcat (s, ", ");
          strcat (s, arg_types[i]);
          strcat (s, arg_types[i]);
        }
        }
      if (varargs)
      if (varargs)
        {
        {
          if (i > 0)
          if (i > 0)
            strcat (s, ", ");
            strcat (s, ", ");
          strcat (s, "...");
          strcat (s, "...");
        }
        }
      if (argcount > 0)
      if (argcount > 0)
        free (arg_types);
        free (arg_types);
    }
    }
 
 
  strcat (s, ")");
  strcat (s, ")");
 
 
  if (! substitute_type (info, s))
  if (! substitute_type (info, s))
    return FALSE;
    return FALSE;
 
 
  free (s);
  free (s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Turn the top type on the stack into a reference to that type.  */
/* Turn the top type on the stack into a reference to that type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_reference_type (void *p)
pr_reference_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  return substitute_type (info, "&|");
  return substitute_type (info, "&|");
}
}
 
 
/* Make a range type.  */
/* Make a range type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_range_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper)
pr_range_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char abl[20], abu[20];
  char abl[20], abu[20];
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  if (! substitute_type (info, ""))
  if (! substitute_type (info, ""))
    return FALSE;
    return FALSE;
 
 
  print_vma (lower, abl, FALSE, FALSE);
  print_vma (lower, abl, FALSE, FALSE);
  print_vma (upper, abu, FALSE, FALSE);
  print_vma (upper, abu, FALSE, FALSE);
 
 
  return (prepend_type (info, "range (")
  return (prepend_type (info, "range (")
          && append_type (info, "):")
          && append_type (info, "):")
          && append_type (info, abl)
          && append_type (info, abl)
          && append_type (info, ":")
          && append_type (info, ":")
          && append_type (info, abu));
          && append_type (info, abu));
}
}
 
 
/* Make an array type.  */
/* Make an array type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper,
pr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper,
               bfd_boolean stringp)
               bfd_boolean stringp)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *range_type;
  char *range_type;
  char abl[20], abu[20], ab[50];
  char abl[20], abu[20], ab[50];
 
 
  range_type = pop_type (info);
  range_type = pop_type (info);
  if (range_type == NULL)
  if (range_type == NULL)
    return FALSE;
    return FALSE;
 
 
  if (lower == 0)
  if (lower == 0)
    {
    {
      if (upper == -1)
      if (upper == -1)
        sprintf (ab, "|[]");
        sprintf (ab, "|[]");
      else
      else
        {
        {
          print_vma (upper + 1, abu, FALSE, FALSE);
          print_vma (upper + 1, abu, FALSE, FALSE);
          sprintf (ab, "|[%s]", abu);
          sprintf (ab, "|[%s]", abu);
        }
        }
    }
    }
  else
  else
    {
    {
      print_vma (lower, abl, FALSE, FALSE);
      print_vma (lower, abl, FALSE, FALSE);
      print_vma (upper, abu, FALSE, FALSE);
      print_vma (upper, abu, FALSE, FALSE);
      sprintf (ab, "|[%s:%s]", abl, abu);
      sprintf (ab, "|[%s:%s]", abl, abu);
    }
    }
 
 
  if (! substitute_type (info, ab))
  if (! substitute_type (info, ab))
    return FALSE;
    return FALSE;
 
 
  if (strcmp (range_type, "int") != 0)
  if (strcmp (range_type, "int") != 0)
    {
    {
      if (! append_type (info, ":")
      if (! append_type (info, ":")
          || ! append_type (info, range_type))
          || ! append_type (info, range_type))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (stringp)
  if (stringp)
    {
    {
      if (! append_type (info, " /* string */"))
      if (! append_type (info, " /* string */"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a set type.  */
/* Make a set type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_set_type (void *p, bfd_boolean bitstringp)
pr_set_type (void *p, bfd_boolean bitstringp)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  if (! substitute_type (info, ""))
  if (! substitute_type (info, ""))
    return FALSE;
    return FALSE;
 
 
  if (! prepend_type (info, "set { ")
  if (! prepend_type (info, "set { ")
      || ! append_type (info, " }"))
      || ! append_type (info, " }"))
    return FALSE;
    return FALSE;
 
 
  if (bitstringp)
  if (bitstringp)
    {
    {
      if (! append_type (info, "/* bitstring */"))
      if (! append_type (info, "/* bitstring */"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make an offset type.  */
/* Make an offset type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_offset_type (void *p)
pr_offset_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  if (! substitute_type (info, ""))
  if (! substitute_type (info, ""))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  return (substitute_type (info, "")
  return (substitute_type (info, "")
          && prepend_type (info, " ")
          && prepend_type (info, " ")
          && prepend_type (info, t)
          && prepend_type (info, t)
          && append_type (info, "::|"));
          && append_type (info, "::|"));
}
}
 
 
/* Make a method type.  */
/* Make a method type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_method_type (void *p, bfd_boolean domain, int argcount, bfd_boolean varargs)
pr_method_type (void *p, bfd_boolean domain, int argcount, bfd_boolean varargs)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  unsigned int len;
  unsigned int len;
  char *domain_type;
  char *domain_type;
  char **arg_types;
  char **arg_types;
  char *s;
  char *s;
 
 
  len = 10;
  len = 10;
 
 
  if (! domain)
  if (! domain)
    domain_type = NULL;
    domain_type = NULL;
  else
  else
    {
    {
      if (! substitute_type (info, ""))
      if (! substitute_type (info, ""))
        return FALSE;
        return FALSE;
      domain_type = pop_type (info);
      domain_type = pop_type (info);
      if (domain_type == NULL)
      if (domain_type == NULL)
        return FALSE;
        return FALSE;
      if (CONST_STRNEQ (domain_type, "class ")
      if (CONST_STRNEQ (domain_type, "class ")
          && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
          && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
        domain_type += sizeof "class " - 1;
        domain_type += sizeof "class " - 1;
      else if (CONST_STRNEQ (domain_type, "union class ")
      else if (CONST_STRNEQ (domain_type, "union class ")
               && (strchr (domain_type + sizeof "union class " - 1, ' ')
               && (strchr (domain_type + sizeof "union class " - 1, ' ')
                   == NULL))
                   == NULL))
        domain_type += sizeof "union class " - 1;
        domain_type += sizeof "union class " - 1;
      len += strlen (domain_type);
      len += strlen (domain_type);
    }
    }
 
 
  if (argcount <= 0)
  if (argcount <= 0)
    {
    {
      arg_types = NULL;
      arg_types = NULL;
      len += 15;
      len += 15;
    }
    }
  else
  else
    {
    {
      int i;
      int i;
 
 
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
      for (i = argcount - 1; i >= 0; i--)
      for (i = argcount - 1; i >= 0; i--)
        {
        {
          if (! substitute_type (info, ""))
          if (! substitute_type (info, ""))
            return FALSE;
            return FALSE;
          arg_types[i] = pop_type (info);
          arg_types[i] = pop_type (info);
          if (arg_types[i] == NULL)
          if (arg_types[i] == NULL)
            return FALSE;
            return FALSE;
          len += strlen (arg_types[i]) + 2;
          len += strlen (arg_types[i]) + 2;
        }
        }
      if (varargs)
      if (varargs)
        len += 5;
        len += 5;
    }
    }
 
 
  /* Now the return type is on the top of the stack.  */
  /* Now the return type is on the top of the stack.  */
 
 
  s = (char *) xmalloc (len);
  s = (char *) xmalloc (len);
  if (! domain)
  if (! domain)
    *s = '\0';
    *s = '\0';
  else
  else
    strcpy (s, domain_type);
    strcpy (s, domain_type);
  strcat (s, "::| (");
  strcat (s, "::| (");
 
 
  if (argcount < 0)
  if (argcount < 0)
    strcat (s, "/* unknown */");
    strcat (s, "/* unknown */");
  else
  else
    {
    {
      int i;
      int i;
 
 
      for (i = 0; i < argcount; i++)
      for (i = 0; i < argcount; i++)
        {
        {
          if (i > 0)
          if (i > 0)
            strcat (s, ", ");
            strcat (s, ", ");
          strcat (s, arg_types[i]);
          strcat (s, arg_types[i]);
        }
        }
      if (varargs)
      if (varargs)
        {
        {
          if (i > 0)
          if (i > 0)
            strcat (s, ", ");
            strcat (s, ", ");
          strcat (s, "...");
          strcat (s, "...");
        }
        }
      if (argcount > 0)
      if (argcount > 0)
        free (arg_types);
        free (arg_types);
    }
    }
 
 
  strcat (s, ")");
  strcat (s, ")");
 
 
  if (! substitute_type (info, s))
  if (! substitute_type (info, s))
    return FALSE;
    return FALSE;
 
 
  free (s);
  free (s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a const qualified type.  */
/* Make a const qualified type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_const_type (void *p)
pr_const_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  return substitute_type (info, "const |");
  return substitute_type (info, "const |");
}
}
 
 
/* Make a volatile qualified type.  */
/* Make a volatile qualified type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_volatile_type (void *p)
pr_volatile_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  return substitute_type (info, "volatile |");
  return substitute_type (info, "volatile |");
}
}
 
 
/* Start accumulating a struct type.  */
/* Start accumulating a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_struct_type (void *p, const char *tag, unsigned int id,
pr_start_struct_type (void *p, const char *tag, unsigned int id,
                      bfd_boolean structp, unsigned int size)
                      bfd_boolean structp, unsigned int size)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  info->indent += 2;
  info->indent += 2;
 
 
  if (! push_type (info, structp ? "struct " : "union "))
  if (! push_type (info, structp ? "struct " : "union "))
    return FALSE;
    return FALSE;
  if (tag != NULL)
  if (tag != NULL)
    {
    {
      if (! append_type (info, tag))
      if (! append_type (info, tag))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      char idbuf[20];
      char idbuf[20];
 
 
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
      if (! append_type (info, idbuf))
      if (! append_type (info, idbuf))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! append_type (info, " {"))
  if (! append_type (info, " {"))
    return FALSE;
    return FALSE;
  if (size != 0 || tag != NULL)
  if (size != 0 || tag != NULL)
    {
    {
      char ab[30];
      char ab[30];
 
 
      if (! append_type (info, " /*"))
      if (! append_type (info, " /*"))
        return FALSE;
        return FALSE;
 
 
      if (size != 0)
      if (size != 0)
        {
        {
          sprintf (ab, " size %u", size);
          sprintf (ab, " size %u", size);
          if (! append_type (info, ab))
          if (! append_type (info, ab))
            return FALSE;
            return FALSE;
        }
        }
      if (tag != NULL)
      if (tag != NULL)
        {
        {
          sprintf (ab, " id %u", id);
          sprintf (ab, " id %u", id);
          if (! append_type (info, ab))
          if (! append_type (info, ab))
            return FALSE;
            return FALSE;
        }
        }
      if (! append_type (info, " */"))
      if (! append_type (info, " */"))
        return FALSE;
        return FALSE;
    }
    }
  if (! append_type (info, "\n"))
  if (! append_type (info, "\n"))
    return FALSE;
    return FALSE;
 
 
  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
 
 
  return indent_type (info);
  return indent_type (info);
}
}
 
 
/* Output the visibility of a field in a struct.  */
/* Output the visibility of a field in a struct.  */
 
 
static bfd_boolean
static bfd_boolean
pr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
pr_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
{
{
  const char *s = NULL;
  const char *s = NULL;
  char *t;
  char *t;
  unsigned int len;
  unsigned int len;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  if (info->stack->visibility == visibility)
  if (info->stack->visibility == visibility)
    return TRUE;
    return TRUE;
 
 
  switch (visibility)
  switch (visibility)
    {
    {
    case DEBUG_VISIBILITY_PUBLIC:
    case DEBUG_VISIBILITY_PUBLIC:
      s = "public";
      s = "public";
      break;
      break;
    case DEBUG_VISIBILITY_PRIVATE:
    case DEBUG_VISIBILITY_PRIVATE:
      s = "private";
      s = "private";
      break;
      break;
    case DEBUG_VISIBILITY_PROTECTED:
    case DEBUG_VISIBILITY_PROTECTED:
      s = "protected";
      s = "protected";
      break;
      break;
    case DEBUG_VISIBILITY_IGNORE:
    case DEBUG_VISIBILITY_IGNORE:
      s = "/* ignore */";
      s = "/* ignore */";
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      return FALSE;
      return FALSE;
    }
    }
 
 
  /* Trim off a trailing space in the struct string, to make the
  /* Trim off a trailing space in the struct string, to make the
     output look a bit better, then stick on the visibility string.  */
     output look a bit better, then stick on the visibility string.  */
 
 
  t = info->stack->type;
  t = info->stack->type;
  len = strlen (t);
  len = strlen (t);
  assert (t[len - 1] == ' ');
  assert (t[len - 1] == ' ');
  t[len - 1] = '\0';
  t[len - 1] = '\0';
 
 
  if (! append_type (info, s)
  if (! append_type (info, s)
      || ! append_type (info, ":\n")
      || ! append_type (info, ":\n")
      || ! indent_type (info))
      || ! indent_type (info))
    return FALSE;
    return FALSE;
 
 
  info->stack->visibility = visibility;
  info->stack->visibility = visibility;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a field to a struct type.  */
/* Add a field to a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
pr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
                 enum debug_visibility visibility)
                 enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
  char *t;
  char *t;
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  if (! append_type (info, "; /* "))
  if (! append_type (info, "; /* "))
    return FALSE;
    return FALSE;
 
 
  if (bitsize != 0)
  if (bitsize != 0)
    {
    {
      print_vma (bitsize, ab, TRUE, FALSE);
      print_vma (bitsize, ab, TRUE, FALSE);
      if (! append_type (info, "bitsize ")
      if (! append_type (info, "bitsize ")
          || ! append_type (info, ab)
          || ! append_type (info, ab)
          || ! append_type (info, ", "))
          || ! append_type (info, ", "))
        return FALSE;
        return FALSE;
    }
    }
 
 
  print_vma (bitpos, ab, TRUE, FALSE);
  print_vma (bitpos, ab, TRUE, FALSE);
  if (! append_type (info, "bitpos ")
  if (! append_type (info, "bitpos ")
      || ! append_type (info, ab)
      || ! append_type (info, ab)
      || ! append_type (info, " */\n")
      || ! append_type (info, " */\n")
      || ! indent_type (info))
      || ! indent_type (info))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (! pr_fix_visibility (info, visibility))
  if (! pr_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  return append_type (info, t);
  return append_type (info, t);
}
}
 
 
/* Finish a struct type.  */
/* Finish a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_end_struct_type (void *p)
pr_end_struct_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *s;
  char *s;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  assert (info->indent >= 2);
  assert (info->indent >= 2);
 
 
  info->indent -= 2;
  info->indent -= 2;
 
 
  /* Change the trailing indentation to have a close brace.  */
  /* Change the trailing indentation to have a close brace.  */
  s = info->stack->type + strlen (info->stack->type) - 2;
  s = info->stack->type + strlen (info->stack->type) - 2;
  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
 
 
  *s++ = '}';
  *s++ = '}';
  *s = '\0';
  *s = '\0';
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a class type.  */
/* Start a class type.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_class_type (void *p, const char *tag, unsigned int id,
pr_start_class_type (void *p, const char *tag, unsigned int id,
                     bfd_boolean structp, unsigned int size,
                     bfd_boolean structp, unsigned int size,
                     bfd_boolean vptr, bfd_boolean ownvptr)
                     bfd_boolean vptr, bfd_boolean ownvptr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *tv = NULL;
  char *tv = NULL;
 
 
  info->indent += 2;
  info->indent += 2;
 
 
  if (vptr && ! ownvptr)
  if (vptr && ! ownvptr)
    {
    {
      tv = pop_type (info);
      tv = pop_type (info);
      if (tv == NULL)
      if (tv == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! push_type (info, structp ? "class " : "union class "))
  if (! push_type (info, structp ? "class " : "union class "))
    return FALSE;
    return FALSE;
  if (tag != NULL)
  if (tag != NULL)
    {
    {
      if (! append_type (info, tag))
      if (! append_type (info, tag))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      char idbuf[20];
      char idbuf[20];
 
 
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
      if (! append_type (info, idbuf))
      if (! append_type (info, idbuf))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! append_type (info, " {"))
  if (! append_type (info, " {"))
    return FALSE;
    return FALSE;
  if (size != 0 || vptr || ownvptr || tag != NULL)
  if (size != 0 || vptr || ownvptr || tag != NULL)
    {
    {
      if (! append_type (info, " /*"))
      if (! append_type (info, " /*"))
        return FALSE;
        return FALSE;
 
 
      if (size != 0)
      if (size != 0)
        {
        {
          char ab[20];
          char ab[20];
 
 
          sprintf (ab, "%u", size);
          sprintf (ab, "%u", size);
          if (! append_type (info, " size ")
          if (! append_type (info, " size ")
              || ! append_type (info, ab))
              || ! append_type (info, ab))
            return FALSE;
            return FALSE;
        }
        }
 
 
      if (vptr)
      if (vptr)
        {
        {
          if (! append_type (info, " vtable "))
          if (! append_type (info, " vtable "))
            return FALSE;
            return FALSE;
          if (ownvptr)
          if (ownvptr)
            {
            {
              if (! append_type (info, "self "))
              if (! append_type (info, "self "))
                return FALSE;
                return FALSE;
            }
            }
          else
          else
            {
            {
              if (! append_type (info, tv)
              if (! append_type (info, tv)
                  || ! append_type (info, " "))
                  || ! append_type (info, " "))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
 
 
      if (tag != NULL)
      if (tag != NULL)
        {
        {
          char ab[30];
          char ab[30];
 
 
          sprintf (ab, " id %u", id);
          sprintf (ab, " id %u", id);
          if (! append_type (info, ab))
          if (! append_type (info, ab))
            return FALSE;
            return FALSE;
        }
        }
 
 
      if (! append_type (info, " */"))
      if (! append_type (info, " */"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
 
 
  return (append_type (info, "\n")
  return (append_type (info, "\n")
          && indent_type (info));
          && indent_type (info));
}
}
 
 
/* Add a static member to a class.  */
/* Add a static member to a class.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_static_member (void *p, const char *name, const char *physname,
pr_class_static_member (void *p, const char *name, const char *physname,
                        enum debug_visibility visibility)
                        enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  if (! prepend_type (info, "static ")
  if (! prepend_type (info, "static ")
      || ! append_type (info, "; /* ")
      || ! append_type (info, "; /* ")
      || ! append_type (info, physname)
      || ! append_type (info, physname)
      || ! append_type (info, " */\n")
      || ! append_type (info, " */\n")
      || ! indent_type (info))
      || ! indent_type (info))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (! pr_fix_visibility (info, visibility))
  if (! pr_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  return append_type (info, t);
  return append_type (info, t);
}
}
 
 
/* Add a base class to a class.  */
/* Add a base class to a class.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
pr_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
                    enum debug_visibility visibility)
                    enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  const char *prefix;
  const char *prefix;
  char ab[20];
  char ab[20];
  char *s, *l, *n;
  char *s, *l, *n;
 
 
  assert (info->stack != NULL && info->stack->next != NULL);
  assert (info->stack != NULL && info->stack->next != NULL);
 
 
  if (! substitute_type (info, ""))
  if (! substitute_type (info, ""))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (CONST_STRNEQ (t, "class "))
  if (CONST_STRNEQ (t, "class "))
    t += sizeof "class " - 1;
    t += sizeof "class " - 1;
 
 
  /* Push it back on to take advantage of the prepend_type and
  /* Push it back on to take advantage of the prepend_type and
     append_type routines.  */
     append_type routines.  */
  if (! push_type (info, t))
  if (! push_type (info, t))
    return FALSE;
    return FALSE;
 
 
  if (virtual)
  if (virtual)
    {
    {
      if (! prepend_type (info, "virtual "))
      if (! prepend_type (info, "virtual "))
        return FALSE;
        return FALSE;
    }
    }
 
 
  switch (visibility)
  switch (visibility)
    {
    {
    case DEBUG_VISIBILITY_PUBLIC:
    case DEBUG_VISIBILITY_PUBLIC:
      prefix = "public ";
      prefix = "public ";
      break;
      break;
    case DEBUG_VISIBILITY_PROTECTED:
    case DEBUG_VISIBILITY_PROTECTED:
      prefix = "protected ";
      prefix = "protected ";
      break;
      break;
    case DEBUG_VISIBILITY_PRIVATE:
    case DEBUG_VISIBILITY_PRIVATE:
      prefix = "private ";
      prefix = "private ";
      break;
      break;
    default:
    default:
      prefix = "/* unknown visibility */ ";
      prefix = "/* unknown visibility */ ";
      break;
      break;
    }
    }
 
 
  if (! prepend_type (info, prefix))
  if (! prepend_type (info, prefix))
    return FALSE;
    return FALSE;
 
 
  if (bitpos != 0)
  if (bitpos != 0)
    {
    {
      print_vma (bitpos, ab, TRUE, FALSE);
      print_vma (bitpos, ab, TRUE, FALSE);
      if (! append_type (info, " /* bitpos ")
      if (! append_type (info, " /* bitpos ")
          || ! append_type (info, ab)
          || ! append_type (info, ab)
          || ! append_type (info, " */"))
          || ! append_type (info, " */"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Now the top of the stack is something like "public A / * bitpos
  /* Now the top of the stack is something like "public A / * bitpos
     10 * /".  The next element on the stack is something like "class
     10 * /".  The next element on the stack is something like "class
     xx { / * size 8 * /\n...".  We want to substitute the top of the
     xx { / * size 8 * /\n...".  We want to substitute the top of the
     stack in before the {.  */
     stack in before the {.  */
  s = strchr (info->stack->next->type, '{');
  s = strchr (info->stack->next->type, '{');
  assert (s != NULL);
  assert (s != NULL);
  --s;
  --s;
 
 
  /* If there is already a ':', then we already have a baseclass, and
  /* If there is already a ':', then we already have a baseclass, and
     we must append this one after a comma.  */
     we must append this one after a comma.  */
  for (l = info->stack->next->type; l != s; l++)
  for (l = info->stack->next->type; l != s; l++)
    if (*l == ':')
    if (*l == ':')
      break;
      break;
  if (! prepend_type (info, l == s ? " : " : ", "))
  if (! prepend_type (info, l == s ? " : " : ", "))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
  memcpy (n, info->stack->type, s - info->stack->type);
  memcpy (n, info->stack->type, s - info->stack->type);
  strcpy (n + (s - info->stack->type), t);
  strcpy (n + (s - info->stack->type), t);
  strcat (n, s);
  strcat (n, s);
 
 
  free (info->stack->type);
  free (info->stack->type);
  info->stack->type = n;
  info->stack->type = n;
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start adding a method to a class.  */
/* Start adding a method to a class.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_start_method (void *p, const char *name)
pr_class_start_method (void *p, const char *name)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  info->stack->method = name;
  info->stack->method = name;
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a variant to a method.  */
/* Add a variant to a method.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_method_variant (void *p, const char *physname,
pr_class_method_variant (void *p, const char *physname,
                         enum debug_visibility visibility,
                         enum debug_visibility visibility,
                         bfd_boolean constp, bfd_boolean volatilep,
                         bfd_boolean constp, bfd_boolean volatilep,
                         bfd_vma voffset, bfd_boolean context)
                         bfd_vma voffset, bfd_boolean context)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *method_type;
  char *method_type;
  char *context_type;
  char *context_type;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next != NULL);
 
 
  /* Put the const and volatile qualifiers on the type.  */
  /* Put the const and volatile qualifiers on the type.  */
  if (volatilep)
  if (volatilep)
    {
    {
      if (! append_type (info, " volatile"))
      if (! append_type (info, " volatile"))
        return FALSE;
        return FALSE;
    }
    }
  if (constp)
  if (constp)
    {
    {
      if (! append_type (info, " const"))
      if (! append_type (info, " const"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Stick the name of the method into its type.  */
  /* Stick the name of the method into its type.  */
  if (! substitute_type (info,
  if (! substitute_type (info,
                         (context
                         (context
                          ? info->stack->next->next->method
                          ? info->stack->next->next->method
                          : info->stack->next->method)))
                          : info->stack->next->method)))
    return FALSE;
    return FALSE;
 
 
  /* Get the type.  */
  /* Get the type.  */
  method_type = pop_type (info);
  method_type = pop_type (info);
  if (method_type == NULL)
  if (method_type == NULL)
    return FALSE;
    return FALSE;
 
 
  /* Pull off the context type if there is one.  */
  /* Pull off the context type if there is one.  */
  if (! context)
  if (! context)
    context_type = NULL;
    context_type = NULL;
  else
  else
    {
    {
      context_type = pop_type (info);
      context_type = pop_type (info);
      if (context_type == NULL)
      if (context_type == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Now the top of the stack is the class.  */
  /* Now the top of the stack is the class.  */
 
 
  if (! pr_fix_visibility (info, visibility))
  if (! pr_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  if (! append_type (info, method_type)
  if (! append_type (info, method_type)
      || ! append_type (info, " /* ")
      || ! append_type (info, " /* ")
      || ! append_type (info, physname)
      || ! append_type (info, physname)
      || ! append_type (info, " "))
      || ! append_type (info, " "))
    return FALSE;
    return FALSE;
  if (context || voffset != 0)
  if (context || voffset != 0)
    {
    {
      char ab[20];
      char ab[20];
 
 
      if (context)
      if (context)
        {
        {
          if (! append_type (info, "context ")
          if (! append_type (info, "context ")
              || ! append_type (info, context_type)
              || ! append_type (info, context_type)
              || ! append_type (info, " "))
              || ! append_type (info, " "))
            return FALSE;
            return FALSE;
        }
        }
      print_vma (voffset, ab, TRUE, FALSE);
      print_vma (voffset, ab, TRUE, FALSE);
      if (! append_type (info, "voffset ")
      if (! append_type (info, "voffset ")
          || ! append_type (info, ab))
          || ! append_type (info, ab))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return (append_type (info, " */;\n")
  return (append_type (info, " */;\n")
          && indent_type (info));
          && indent_type (info));
}
}
 
 
/* Add a static variant to a method.  */
/* Add a static variant to a method.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_static_method_variant (void *p, const char *physname,
pr_class_static_method_variant (void *p, const char *physname,
                                enum debug_visibility visibility,
                                enum debug_visibility visibility,
                                bfd_boolean constp, bfd_boolean volatilep)
                                bfd_boolean constp, bfd_boolean volatilep)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *method_type;
  char *method_type;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next->method != NULL);
  assert (info->stack->next->method != NULL);
 
 
  /* Put the const and volatile qualifiers on the type.  */
  /* Put the const and volatile qualifiers on the type.  */
  if (volatilep)
  if (volatilep)
    {
    {
      if (! append_type (info, " volatile"))
      if (! append_type (info, " volatile"))
        return FALSE;
        return FALSE;
    }
    }
  if (constp)
  if (constp)
    {
    {
      if (! append_type (info, " const"))
      if (! append_type (info, " const"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Mark it as static.  */
  /* Mark it as static.  */
  if (! prepend_type (info, "static "))
  if (! prepend_type (info, "static "))
    return FALSE;
    return FALSE;
 
 
  /* Stick the name of the method into its type.  */
  /* Stick the name of the method into its type.  */
  if (! substitute_type (info, info->stack->next->method))
  if (! substitute_type (info, info->stack->next->method))
    return FALSE;
    return FALSE;
 
 
  /* Get the type.  */
  /* Get the type.  */
  method_type = pop_type (info);
  method_type = pop_type (info);
  if (method_type == NULL)
  if (method_type == NULL)
    return FALSE;
    return FALSE;
 
 
  /* Now the top of the stack is the class.  */
  /* Now the top of the stack is the class.  */
 
 
  if (! pr_fix_visibility (info, visibility))
  if (! pr_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  return (append_type (info, method_type)
  return (append_type (info, method_type)
          && append_type (info, " /* ")
          && append_type (info, " /* ")
          && append_type (info, physname)
          && append_type (info, physname)
          && append_type (info, " */;\n")
          && append_type (info, " */;\n")
          && indent_type (info));
          && indent_type (info));
}
}
 
 
/* Finish up a method.  */
/* Finish up a method.  */
 
 
static bfd_boolean
static bfd_boolean
pr_class_end_method (void *p)
pr_class_end_method (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  info->stack->method = NULL;
  info->stack->method = NULL;
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish up a class.  */
/* Finish up a class.  */
 
 
static bfd_boolean
static bfd_boolean
pr_end_class_type (void *p)
pr_end_class_type (void *p)
{
{
  return pr_end_struct_type (p);
  return pr_end_struct_type (p);
}
}
 
 
/* Push a type on the stack using a typedef name.  */
/* Push a type on the stack using a typedef name.  */
 
 
static bfd_boolean
static bfd_boolean
pr_typedef_type (void *p, const char *name)
pr_typedef_type (void *p, const char *name)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  return push_type (info, name);
  return push_type (info, name);
}
}
 
 
/* Push a type on the stack using a tag name.  */
/* Push a type on the stack using a tag name.  */
 
 
static bfd_boolean
static bfd_boolean
pr_tag_type (void *p, const char *name, unsigned int id,
pr_tag_type (void *p, const char *name, unsigned int id,
             enum debug_type_kind kind)
             enum debug_type_kind kind)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  const char *t, *tag;
  const char *t, *tag;
  char idbuf[20];
  char idbuf[20];
 
 
  switch (kind)
  switch (kind)
    {
    {
    case DEBUG_KIND_STRUCT:
    case DEBUG_KIND_STRUCT:
      t = "struct ";
      t = "struct ";
      break;
      break;
    case DEBUG_KIND_UNION:
    case DEBUG_KIND_UNION:
      t = "union ";
      t = "union ";
      break;
      break;
    case DEBUG_KIND_ENUM:
    case DEBUG_KIND_ENUM:
      t = "enum ";
      t = "enum ";
      break;
      break;
    case DEBUG_KIND_CLASS:
    case DEBUG_KIND_CLASS:
      t = "class ";
      t = "class ";
      break;
      break;
    case DEBUG_KIND_UNION_CLASS:
    case DEBUG_KIND_UNION_CLASS:
      t = "union class ";
      t = "union class ";
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      return FALSE;
      return FALSE;
    }
    }
 
 
  if (! push_type (info, t))
  if (! push_type (info, t))
    return FALSE;
    return FALSE;
  if (name != NULL)
  if (name != NULL)
    tag = name;
    tag = name;
  else
  else
    {
    {
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
      tag = idbuf;
      tag = idbuf;
    }
    }
 
 
  if (! append_type (info, tag))
  if (! append_type (info, tag))
    return FALSE;
    return FALSE;
  if (name != NULL && kind != DEBUG_KIND_ENUM)
  if (name != NULL && kind != DEBUG_KIND_ENUM)
    {
    {
      sprintf (idbuf, " /* id %u */", id);
      sprintf (idbuf, " /* id %u */", id);
      if (! append_type (info, idbuf))
      if (! append_type (info, idbuf))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typedef.  */
/* Output a typedef.  */
 
 
static bfd_boolean
static bfd_boolean
pr_typdef (void *p, const char *name)
pr_typdef (void *p, const char *name)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *s;
  char *s;
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  s = pop_type (info);
  s = pop_type (info);
  if (s == NULL)
  if (s == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  fprintf (info->f, "typedef %s;\n", s);
  fprintf (info->f, "typedef %s;\n", s);
 
 
  free (s);
  free (s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a tag.  The tag should already be in the string on the
/* Output a tag.  The tag should already be in the string on the
   stack, so all we have to do here is print it out.  */
   stack, so all we have to do here is print it out.  */
 
 
static bfd_boolean
static bfd_boolean
pr_tag (void *p, const char *name ATTRIBUTE_UNUSED)
pr_tag (void *p, const char *name ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  fprintf (info->f, "%s;\n", t);
  fprintf (info->f, "%s;\n", t);
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output an integer constant.  */
/* Output an integer constant.  */
 
 
static bfd_boolean
static bfd_boolean
pr_int_constant (void *p, const char *name, bfd_vma val)
pr_int_constant (void *p, const char *name, bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
 
 
  indent (info);
  indent (info);
  print_vma (val, ab, FALSE, FALSE);
  print_vma (val, ab, FALSE, FALSE);
  fprintf (info->f, "const int %s = %s;\n", name, ab);
  fprintf (info->f, "const int %s = %s;\n", name, ab);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a floating point constant.  */
/* Output a floating point constant.  */
 
 
static bfd_boolean
static bfd_boolean
pr_float_constant (void *p, const char *name, double val)
pr_float_constant (void *p, const char *name, double val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  indent (info);
  indent (info);
  fprintf (info->f, "const double %s = %g;\n", name, val);
  fprintf (info->f, "const double %s = %g;\n", name, val);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typed constant.  */
/* Output a typed constant.  */
 
 
static bfd_boolean
static bfd_boolean
pr_typed_constant (void *p, const char *name, bfd_vma val)
pr_typed_constant (void *p, const char *name, bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  char ab[20];
  char ab[20];
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  print_vma (val, ab, FALSE, FALSE);
  print_vma (val, ab, FALSE, FALSE);
  fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
  fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a variable.  */
/* Output a variable.  */
 
 
static bfd_boolean
static bfd_boolean
pr_variable (void *p, const char *name, enum debug_var_kind kind,
pr_variable (void *p, const char *name, enum debug_var_kind kind,
             bfd_vma val)
             bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  char ab[20];
  char ab[20];
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  switch (kind)
  switch (kind)
    {
    {
    case DEBUG_STATIC:
    case DEBUG_STATIC:
    case DEBUG_LOCAL_STATIC:
    case DEBUG_LOCAL_STATIC:
      fprintf (info->f, "static ");
      fprintf (info->f, "static ");
      break;
      break;
    case DEBUG_REGISTER:
    case DEBUG_REGISTER:
      fprintf (info->f, "register ");
      fprintf (info->f, "register ");
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  print_vma (val, ab, TRUE, TRUE);
  print_vma (val, ab, TRUE, TRUE);
  fprintf (info->f, "%s /* %s */;\n", t, ab);
  fprintf (info->f, "%s /* %s */;\n", t, ab);
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start outputting a function.  */
/* Start outputting a function.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_function (void *p, const char *name, bfd_boolean global)
pr_start_function (void *p, const char *name, bfd_boolean global)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  if (! global)
  if (! global)
    fprintf (info->f, "static ");
    fprintf (info->f, "static ");
  fprintf (info->f, "%s (", t);
  fprintf (info->f, "%s (", t);
 
 
  info->parameter = 1;
  info->parameter = 1;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a function parameter.  */
/* Output a function parameter.  */
 
 
static bfd_boolean
static bfd_boolean
pr_function_parameter (void *p, const char *name,
pr_function_parameter (void *p, const char *name,
                       enum debug_parm_kind kind, bfd_vma val)
                       enum debug_parm_kind kind, bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  char ab[20];
  char ab[20];
 
 
  if (kind == DEBUG_PARM_REFERENCE
  if (kind == DEBUG_PARM_REFERENCE
      || kind == DEBUG_PARM_REF_REG)
      || kind == DEBUG_PARM_REF_REG)
    {
    {
      if (! pr_reference_type (p))
      if (! pr_reference_type (p))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (info->parameter != 1)
  if (info->parameter != 1)
    fprintf (info->f, ", ");
    fprintf (info->f, ", ");
 
 
  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
    fprintf (info->f, "register ");
    fprintf (info->f, "register ");
 
 
  print_vma (val, ab, TRUE, TRUE);
  print_vma (val, ab, TRUE, TRUE);
  fprintf (info->f, "%s /* %s */", t, ab);
  fprintf (info->f, "%s /* %s */", t, ab);
 
 
  free (t);
  free (t);
 
 
  ++info->parameter;
  ++info->parameter;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start writing out a block.  */
/* Start writing out a block.  */
 
 
static bfd_boolean
static bfd_boolean
pr_start_block (void *p, bfd_vma addr)
pr_start_block (void *p, bfd_vma addr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
 
 
  if (info->parameter > 0)
  if (info->parameter > 0)
    {
    {
      fprintf (info->f, ")\n");
      fprintf (info->f, ")\n");
      info->parameter = 0;
      info->parameter = 0;
    }
    }
 
 
  indent (info);
  indent (info);
  print_vma (addr, ab, TRUE, TRUE);
  print_vma (addr, ab, TRUE, TRUE);
  fprintf (info->f, "{ /* %s */\n", ab);
  fprintf (info->f, "{ /* %s */\n", ab);
 
 
  info->indent += 2;
  info->indent += 2;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out line number information.  */
/* Write out line number information.  */
 
 
static bfd_boolean
static bfd_boolean
pr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
pr_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
 
 
  indent (info);
  indent (info);
  print_vma (addr, ab, TRUE, TRUE);
  print_vma (addr, ab, TRUE, TRUE);
  fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
  fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish writing out a block.  */
/* Finish writing out a block.  */
 
 
static bfd_boolean
static bfd_boolean
pr_end_block (void *p, bfd_vma addr)
pr_end_block (void *p, bfd_vma addr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
 
 
  info->indent -= 2;
  info->indent -= 2;
 
 
  indent (info);
  indent (info);
  print_vma (addr, ab, TRUE, TRUE);
  print_vma (addr, ab, TRUE, TRUE);
  fprintf (info->f, "} /* %s */\n", ab);
  fprintf (info->f, "} /* %s */\n", ab);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish writing out a function.  */
/* Finish writing out a function.  */
 
 
static bfd_boolean
static bfd_boolean
pr_end_function (void *p ATTRIBUTE_UNUSED)
pr_end_function (void *p ATTRIBUTE_UNUSED)
{
{
  return TRUE;
  return TRUE;
}
}


/* Tags style generation functions start here.  */
/* Tags style generation functions start here.  */
 
 
/* Variables for address to line translation.  */
/* Variables for address to line translation.  */
static bfd_vma pc;
static bfd_vma pc;
static const char *filename;
static const char *filename;
static const char *functionname;
static const char *functionname;
static unsigned int line;
static unsigned int line;
static bfd_boolean found;
static bfd_boolean found;
 
 
/* Look for an address in a section.  This is called via
/* Look for an address in a section.  This is called via
   bfd_map_over_sections.  */
   bfd_map_over_sections.  */
 
 
static void
static void
find_address_in_section (bfd *abfd, asection *section, void *data)
find_address_in_section (bfd *abfd, asection *section, void *data)
{
{
  bfd_vma vma;
  bfd_vma vma;
  bfd_size_type size;
  bfd_size_type size;
  asymbol **syms = (asymbol **) data;
  asymbol **syms = (asymbol **) data;
 
 
  if (found)
  if (found)
    return;
    return;
 
 
  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
    return;
    return;
 
 
  vma = bfd_get_section_vma (abfd, section);
  vma = bfd_get_section_vma (abfd, section);
  if (pc < vma)
  if (pc < vma)
    return;
    return;
 
 
  size = bfd_get_section_size (section);
  size = bfd_get_section_size (section);
  if (pc >= vma + size)
  if (pc >= vma + size)
    return;
    return;
 
 
  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
                                 &filename, &functionname, &line);
                                 &filename, &functionname, &line);
}
}
 
 
static void
static void
translate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms)
translate_addresses (bfd *abfd, char *addr_hex, FILE *f, asymbol **syms)
{
{
  pc = bfd_scan_vma (addr_hex, NULL, 16);
  pc = bfd_scan_vma (addr_hex, NULL, 16);
  found = FALSE;
  found = FALSE;
  bfd_map_over_sections (abfd, find_address_in_section, syms);
  bfd_map_over_sections (abfd, find_address_in_section, syms);
 
 
  if (! found)
  if (! found)
    fprintf (f, "??");
    fprintf (f, "??");
  else
  else
    fprintf (f, "%u", line);
    fprintf (f, "%u", line);
}
}
 
 
/* Start a new compilation unit.  */
/* Start a new compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED)
tg_start_compilation_unit (void * p, const char *filename ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  free (info->filename);
  free (info->filename);
  /* Should it be relative? best way to do it here?.  */
  /* Should it be relative? best way to do it here?.  */
  info->filename = strdup (filename);
  info->filename = strdup (filename);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a source file within a compilation unit.  */
/* Start a source file within a compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_source (void *p, const char *filename)
tg_start_source (void *p, const char *filename)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  free (info->filename);
  free (info->filename);
  /* Should it be relative? best way to do it here?.  */
  /* Should it be relative? best way to do it here?.  */
  info->filename = strdup (filename);
  info->filename = strdup (filename);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Push an enum type onto the type stack.  */
/* Push an enum type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
tg_enum_type (void *p, const char *tag, const char **names,
tg_enum_type (void *p, const char *tag, const char **names,
              bfd_signed_vma *values)
              bfd_signed_vma *values)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  unsigned int i;
  unsigned int i;
  const char *name;
  const char *name;
  char ab[20];
  char ab[20];
 
 
  if (! pr_enum_type (p, tag, names, values))
  if (! pr_enum_type (p, tag, names, values))
    return FALSE;
    return FALSE;
 
 
  name = tag ? tag : "unknown";
  name = tag ? tag : "unknown";
  /* Generate an entry for the enum.  */
  /* Generate an entry for the enum.  */
  if (tag)
  if (tag)
    fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag,
    fprintf (info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag,
             info->filename, info->stack->type);
             info->filename, info->stack->type);
 
 
  /* Generate entries for the values.  */
  /* Generate entries for the values.  */
  if (names != NULL)
  if (names != NULL)
    {
    {
      for (i = 0; names[i] != NULL; i++)
      for (i = 0; names[i] != NULL; i++)
        {
        {
          print_vma (values[i], ab, FALSE, FALSE);
          print_vma (values[i], ab, FALSE, FALSE);
          fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n",
          fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n",
                   names[i], info->filename, name, ab);
                   names[i], info->filename, name, ab);
        }
        }
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start accumulating a struct type.  */
/* Start accumulating a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_struct_type (void *p, const char *tag, unsigned int id,
tg_start_struct_type (void *p, const char *tag, unsigned int id,
                      bfd_boolean structp,
                      bfd_boolean structp,
                      unsigned int size ATTRIBUTE_UNUSED)
                      unsigned int size ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  const char *name;
  const char *name;
  char idbuf[20];
  char idbuf[20];
 
 
  if (tag != NULL)
  if (tag != NULL)
    name = tag;
    name = tag;
  else
  else
    {
    {
      name = idbuf;
      name = idbuf;
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
    }
    }
 
 
  if (! push_type (info, name))
  if (! push_type (info, name))
    return FALSE;
    return FALSE;
 
 
  info->stack->flavor = structp ? "struct" : "union";
  info->stack->flavor = structp ? "struct" : "union";
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename,
  fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename,
           info->stack->flavor[0]);
           info->stack->flavor[0]);
 
 
  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
 
 
  return indent_type (info);
  return indent_type (info);
}
}
 
 
/* Output the visibility of a field in a struct.  */
/* Output the visibility of a field in a struct.  */
 
 
static bfd_boolean
static bfd_boolean
tg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
tg_fix_visibility (struct pr_handle *info, enum debug_visibility visibility)
{
{
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  if (info->stack->visibility == visibility)
  if (info->stack->visibility == visibility)
    return TRUE;
    return TRUE;
 
 
  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
 
 
  info->stack->visibility = visibility;
  info->stack->visibility = visibility;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a field to a struct type.  */
/* Add a field to a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
tg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED,
tg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED,
                 bfd_vma bitsize ATTRIBUTE_UNUSED,
                 bfd_vma bitsize ATTRIBUTE_UNUSED,
                 enum debug_visibility visibility)
                 enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (! tg_fix_visibility (info, visibility))
  if (! tg_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  /* It happens, a bug? */
  /* It happens, a bug? */
  if (! name[0])
  if (! name[0])
    return TRUE;
    return TRUE;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
           name, info->filename, t, info->stack->flavor, info->stack->type,
           name, info->filename, t, info->stack->flavor, info->stack->type,
           visibility_name (visibility));
           visibility_name (visibility));
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish a struct type.  */
/* Finish a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
tg_end_struct_type (void *p ATTRIBUTE_UNUSED)
tg_end_struct_type (void *p ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  assert (info->stack != NULL);
  assert (info->stack != NULL);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a class type.  */
/* Start a class type.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_class_type (void *p, const char *tag, unsigned int id,
tg_start_class_type (void *p, const char *tag, unsigned int id,
                     bfd_boolean structp, unsigned int size,
                     bfd_boolean structp, unsigned int size,
                     bfd_boolean vptr, bfd_boolean ownvptr)
                     bfd_boolean vptr, bfd_boolean ownvptr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *tv = NULL;
  char *tv = NULL;
  const char *name;
  const char *name;
 
 
  info->indent += 2;
  info->indent += 2;
 
 
  if (vptr && ! ownvptr)
  if (vptr && ! ownvptr)
    {
    {
      tv = pop_type (info);
      tv = pop_type (info);
      if (tv == NULL)
      if (tv == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (tag != NULL)
  if (tag != NULL)
    name = tag;
    name = tag;
  else
  else
    {
    {
      char idbuf[20];
      char idbuf[20];
 
 
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
      name = idbuf;
      name = idbuf;
    }
    }
 
 
  if (! push_type (info, name))
  if (! push_type (info, name))
    return FALSE;
    return FALSE;
 
 
  info->stack->flavor = structp ? "class" : "union class";
  info->stack->flavor = structp ? "class" : "union class";
  info->stack->parents = NULL;
  info->stack->parents = NULL;
  info->stack->num_parents = 0;
  info->stack->num_parents = 0;
 
 
  if (size != 0 || vptr || ownvptr || tag != NULL)
  if (size != 0 || vptr || ownvptr || tag != NULL)
    {
    {
      if (vptr)
      if (vptr)
        {
        {
          if (! append_type (info, " vtable "))
          if (! append_type (info, " vtable "))
            return FALSE;
            return FALSE;
          if (ownvptr)
          if (ownvptr)
            {
            {
              if (! append_type (info, "self "))
              if (! append_type (info, "self "))
                return FALSE;
                return FALSE;
            }
            }
          else
          else
            {
            {
              if (! append_type (info, tv)
              if (! append_type (info, tv)
                  || ! append_type (info, " "))
                  || ! append_type (info, " "))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
    }
    }
 
 
  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a static member to a class.  */
/* Add a static member to a class.  */
 
 
static bfd_boolean
static bfd_boolean
tg_class_static_member (void *p, const char *name,
tg_class_static_member (void *p, const char *name,
                        const char *physname ATTRIBUTE_UNUSED,
                        const char *physname ATTRIBUTE_UNUSED,
                        enum debug_visibility visibility)
                        enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  int len_var, len_class;
  int len_var, len_class;
  char *full_name;
  char *full_name;
 
 
  len_var = strlen (name);
  len_var = strlen (name);
  len_class = strlen (info->stack->next->type);
  len_class = strlen (info->stack->next->type);
  full_name = xmalloc (len_var + len_class + 3);
  full_name = xmalloc (len_var + len_class + 3);
  if (! full_name)
  if (! full_name)
    return FALSE;
    return FALSE;
  sprintf (full_name, "%s::%s", info->stack->next->type, name);
  sprintf (full_name, "%s::%s", info->stack->next->type, name);
 
 
  if (! substitute_type (info, full_name))
  if (! substitute_type (info, full_name))
    return FALSE;
    return FALSE;
 
 
  if (! prepend_type (info, "static "))
  if (! prepend_type (info, "static "))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (! tg_fix_visibility (info, visibility))
  if (! tg_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n",
           name, info->filename, t, info->stack->type,
           name, info->filename, t, info->stack->type,
           visibility_name (visibility));
           visibility_name (visibility));
  free (t);
  free (t);
  free (full_name);
  free (full_name);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a base class to a class.  */
/* Add a base class to a class.  */
 
 
static bfd_boolean
static bfd_boolean
tg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
tg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
                    bfd_boolean virtual, enum debug_visibility visibility)
                    bfd_boolean virtual, enum debug_visibility visibility)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  const char *prefix;
  const char *prefix;
 
 
  assert (info->stack != NULL && info->stack->next != NULL);
  assert (info->stack != NULL && info->stack->next != NULL);
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (CONST_STRNEQ (t, "class "))
  if (CONST_STRNEQ (t, "class "))
    t += sizeof "class " - 1;
    t += sizeof "class " - 1;
 
 
  /* Push it back on to take advantage of the prepend_type and
  /* Push it back on to take advantage of the prepend_type and
     append_type routines.  */
     append_type routines.  */
  if (! push_type (info, t))
  if (! push_type (info, t))
    return FALSE;
    return FALSE;
 
 
  if (virtual)
  if (virtual)
    {
    {
      if (! prepend_type (info, "virtual "))
      if (! prepend_type (info, "virtual "))
        return FALSE;
        return FALSE;
    }
    }
 
 
  switch (visibility)
  switch (visibility)
    {
    {
    case DEBUG_VISIBILITY_PUBLIC:
    case DEBUG_VISIBILITY_PUBLIC:
      prefix = "public ";
      prefix = "public ";
      break;
      break;
    case DEBUG_VISIBILITY_PROTECTED:
    case DEBUG_VISIBILITY_PROTECTED:
      prefix = "protected ";
      prefix = "protected ";
      break;
      break;
    case DEBUG_VISIBILITY_PRIVATE:
    case DEBUG_VISIBILITY_PRIVATE:
      prefix = "private ";
      prefix = "private ";
      break;
      break;
    default:
    default:
      prefix = "/* unknown visibility */ ";
      prefix = "/* unknown visibility */ ";
      break;
      break;
    }
    }
 
 
  if (! prepend_type (info, prefix))
  if (! prepend_type (info, prefix))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (info->stack->num_parents && ! append_parent (info, ", "))
  if (info->stack->num_parents && ! append_parent (info, ", "))
    return FALSE;
    return FALSE;
 
 
  if (! append_parent (info, t))
  if (! append_parent (info, t))
    return FALSE;
    return FALSE;
  info->stack->num_parents++;
  info->stack->num_parents++;
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a variant to a method.  */
/* Add a variant to a method.  */
 
 
static bfd_boolean
static bfd_boolean
tg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED,
tg_class_method_variant (void *p, const char *physname ATTRIBUTE_UNUSED,
                         enum debug_visibility visibility,
                         enum debug_visibility visibility,
                         bfd_boolean constp, bfd_boolean volatilep,
                         bfd_boolean constp, bfd_boolean volatilep,
                         bfd_vma voffset ATTRIBUTE_UNUSED,
                         bfd_vma voffset ATTRIBUTE_UNUSED,
                         bfd_boolean context)
                         bfd_boolean context)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *method_type;
  char *method_type;
  char *context_type;
  char *context_type;
  char *method_name;
  char *method_name;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next != NULL);
 
 
  /* Put the const and volatile qualifiers on the type.  */
  /* Put the const and volatile qualifiers on the type.  */
  if (volatilep)
  if (volatilep)
    {
    {
      if (! append_type (info, " volatile"))
      if (! append_type (info, " volatile"))
        return FALSE;
        return FALSE;
    }
    }
  if (constp)
  if (constp)
    {
    {
      if (! append_type (info, " const"))
      if (! append_type (info, " const"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  method_name = strdup (context ? info->stack->next->next->method
  method_name = strdup (context ? info->stack->next->next->method
                        : info->stack->next->method);
                        : info->stack->next->method);
 
 
  /* Stick the name of the method into its type.  */
  /* Stick the name of the method into its type.  */
  if (! substitute_type (info, method_name))
  if (! substitute_type (info, method_name))
    return FALSE;
    return FALSE;
 
 
  /* Get the type.  */
  /* Get the type.  */
  method_type = pop_type (info);
  method_type = pop_type (info);
  if (method_type == NULL)
  if (method_type == NULL)
    return FALSE;
    return FALSE;
 
 
  /* Pull off the context type if there is one.  */
  /* Pull off the context type if there is one.  */
  if (! context)
  if (! context)
    context_type = NULL;
    context_type = NULL;
  else
  else
    {
    {
      context_type = pop_type (info);
      context_type = pop_type (info);
      if (context_type == NULL)
      if (context_type == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Now the top of the stack is the class.  */
  /* Now the top of the stack is the class.  */
  if (! tg_fix_visibility (info, visibility))
  if (! tg_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n",
           method_name, info->filename, method_type, info->stack->type);
           method_name, info->filename, method_type, info->stack->type);
  free (method_type);
  free (method_type);
  free (method_name);
  free (method_name);
  free (context_type);
  free (context_type);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a static variant to a method.  */
/* Add a static variant to a method.  */
 
 
static bfd_boolean
static bfd_boolean
tg_class_static_method_variant (void *p,
tg_class_static_method_variant (void *p,
                                const char *physname ATTRIBUTE_UNUSED,
                                const char *physname ATTRIBUTE_UNUSED,
                                enum debug_visibility visibility,
                                enum debug_visibility visibility,
                                bfd_boolean constp, bfd_boolean volatilep)
                                bfd_boolean constp, bfd_boolean volatilep)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *method_type;
  char *method_type;
  char *method_name;
  char *method_name;
 
 
  assert (info->stack != NULL);
  assert (info->stack != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next != NULL);
  assert (info->stack->next->method != NULL);
  assert (info->stack->next->method != NULL);
 
 
  /* Put the const and volatile qualifiers on the type.  */
  /* Put the const and volatile qualifiers on the type.  */
  if (volatilep)
  if (volatilep)
    {
    {
      if (! append_type (info, " volatile"))
      if (! append_type (info, " volatile"))
        return FALSE;
        return FALSE;
    }
    }
  if (constp)
  if (constp)
    {
    {
      if (! append_type (info, " const"))
      if (! append_type (info, " const"))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Mark it as static.  */
  /* Mark it as static.  */
  if (! prepend_type (info, "static "))
  if (! prepend_type (info, "static "))
    return FALSE;
    return FALSE;
 
 
  method_name = strdup (info->stack->next->method);
  method_name = strdup (info->stack->next->method);
  /* Stick the name of the method into its type.  */
  /* Stick the name of the method into its type.  */
  if (! substitute_type (info, info->stack->next->method))
  if (! substitute_type (info, info->stack->next->method))
    return FALSE;
    return FALSE;
 
 
  /* Get the type.  */
  /* Get the type.  */
  method_type = pop_type (info);
  method_type = pop_type (info);
  if (method_type == NULL)
  if (method_type == NULL)
    return FALSE;
    return FALSE;
 
 
  /* Now the top of the stack is the class.  */
  /* Now the top of the stack is the class.  */
  if (! tg_fix_visibility (info, visibility))
  if (! tg_fix_visibility (info, visibility))
    return FALSE;
    return FALSE;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n",
           method_name, info->filename, method_type, info->stack->type,
           method_name, info->filename, method_type, info->stack->type,
           visibility_name (visibility));
           visibility_name (visibility));
  free (method_type);
  free (method_type);
  free (method_name);
  free (method_name);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish up a class.  */
/* Finish up a class.  */
 
 
static bfd_boolean
static bfd_boolean
tg_end_class_type (void *p)
tg_end_class_type (void *p)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type,
  fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type,
           info->filename, info->stack->flavor);
           info->filename, info->stack->flavor);
  if (info->stack->num_parents)
  if (info->stack->num_parents)
    {
    {
      fprintf  (info->f, "\tinherits:%s", info->stack->parents);
      fprintf  (info->f, "\tinherits:%s", info->stack->parents);
      free (info->stack->parents);
      free (info->stack->parents);
    }
    }
  fputc ('\n', info->f);
  fputc ('\n', info->f);
 
 
  return tg_end_struct_type (p);
  return tg_end_struct_type (p);
}
}
 
 
/* Push a type on the stack using a tag name.  */
/* Push a type on the stack using a tag name.  */
 
 
static bfd_boolean
static bfd_boolean
tg_tag_type (void *p, const char *name, unsigned int id,
tg_tag_type (void *p, const char *name, unsigned int id,
             enum debug_type_kind kind)
             enum debug_type_kind kind)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  const char *t, *tag;
  const char *t, *tag;
  char idbuf[20];
  char idbuf[20];
 
 
  switch (kind)
  switch (kind)
    {
    {
    case DEBUG_KIND_STRUCT:
    case DEBUG_KIND_STRUCT:
      t = "struct ";
      t = "struct ";
      break;
      break;
    case DEBUG_KIND_UNION:
    case DEBUG_KIND_UNION:
      t = "union ";
      t = "union ";
      break;
      break;
    case DEBUG_KIND_ENUM:
    case DEBUG_KIND_ENUM:
      t = "enum ";
      t = "enum ";
      break;
      break;
    case DEBUG_KIND_CLASS:
    case DEBUG_KIND_CLASS:
      t = "class ";
      t = "class ";
      break;
      break;
    case DEBUG_KIND_UNION_CLASS:
    case DEBUG_KIND_UNION_CLASS:
      t = "union class ";
      t = "union class ";
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      return FALSE;
      return FALSE;
    }
    }
 
 
  if (! push_type (info, t))
  if (! push_type (info, t))
    return FALSE;
    return FALSE;
  if (name != NULL)
  if (name != NULL)
    tag = name;
    tag = name;
  else
  else
    {
    {
      sprintf (idbuf, "%%anon%u", id);
      sprintf (idbuf, "%%anon%u", id);
      tag = idbuf;
      tag = idbuf;
    }
    }
 
 
  if (! append_type (info, tag))
  if (! append_type (info, tag))
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typedef.  */
/* Output a typedef.  */
 
 
static bfd_boolean
static bfd_boolean
tg_typdef (void *p, const char *name)
tg_typdef (void *p, const char *name)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *s;
  char *s;
 
 
  s = pop_type (info);
  s = pop_type (info);
  if (s == NULL)
  if (s == NULL)
    return FALSE;
    return FALSE;
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name,
  fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name,
           info->filename, s);
           info->filename, s);
 
 
  free (s);
  free (s);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a tag.  The tag should already be in the string on the
/* Output a tag.  The tag should already be in the string on the
   stack, so all we have to do here is print it out.  */
   stack, so all we have to do here is print it out.  */
 
 
static bfd_boolean
static bfd_boolean
tg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED)
tg_tag (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output an integer constant.  */
/* Output an integer constant.  */
 
 
static bfd_boolean
static bfd_boolean
tg_int_constant (void *p, const char *name, bfd_vma val)
tg_int_constant (void *p, const char *name, bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20];
  char ab[20];
 
 
  indent (info);
  indent (info);
  print_vma (val, ab, FALSE, FALSE);
  print_vma (val, ab, FALSE, FALSE);
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n",
           name, info->filename, ab);
           name, info->filename, ab);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a floating point constant.  */
/* Output a floating point constant.  */
 
 
static bfd_boolean
static bfd_boolean
tg_float_constant (void *p, const char *name, double val)
tg_float_constant (void *p, const char *name, double val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
 
 
  indent (info);
  indent (info);
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n",
           name, info->filename, val);
           name, info->filename, val);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typed constant.  */
/* Output a typed constant.  */
 
 
static bfd_boolean
static bfd_boolean
tg_typed_constant (void *p, const char *name, bfd_vma val)
tg_typed_constant (void *p, const char *name, bfd_vma val)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
  char ab[20];
  char ab[20];
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  indent (info);
  indent (info);
  print_vma (val, ab, FALSE, FALSE);
  print_vma (val, ab, FALSE, FALSE);
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n",
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n",
           name, info->filename, t, ab);
           name, info->filename, t, ab);
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a variable.  */
/* Output a variable.  */
 
 
static bfd_boolean
static bfd_boolean
tg_variable (void *p, const char *name, enum debug_var_kind kind,
tg_variable (void *p, const char *name, enum debug_var_kind kind,
             bfd_vma val ATTRIBUTE_UNUSED)
             bfd_vma val ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t, *dname, *from_class;
  char *t, *dname, *from_class;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  dname = NULL;
  dname = NULL;
  if (info->demangler)
  if (info->demangler)
    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
 
 
  from_class = NULL;
  from_class = NULL;
  if (dname != NULL)
  if (dname != NULL)
    {
    {
      char *sep;
      char *sep;
      sep = strstr (dname, "::");
      sep = strstr (dname, "::");
      if (sep)
      if (sep)
        {
        {
          *sep = 0;
          *sep = 0;
          name = sep + 2;
          name = sep + 2;
          from_class = dname;
          from_class = dname;
        }
        }
      else
      else
        /* Obscure types as vts and type_info nodes.  */
        /* Obscure types as vts and type_info nodes.  */
        name = dname;
        name = dname;
    }
    }
 
 
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t);
  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", name, info->filename, t);
 
 
  switch (kind)
  switch (kind)
    {
    {
    case DEBUG_STATIC:
    case DEBUG_STATIC:
    case DEBUG_LOCAL_STATIC:
    case DEBUG_LOCAL_STATIC:
      fprintf (info->f, "\tfile:");
      fprintf (info->f, "\tfile:");
      break;
      break;
    case DEBUG_REGISTER:
    case DEBUG_REGISTER:
      fprintf (info->f, "\tregister:");
      fprintf (info->f, "\tregister:");
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  if (from_class)
  if (from_class)
    fprintf (info->f, "\tclass:%s", from_class);
    fprintf (info->f, "\tclass:%s", from_class);
 
 
  if (dname)
  if (dname)
    free (dname);
    free (dname);
 
 
  fprintf (info->f, "\n");
  fprintf (info->f, "\n");
 
 
  free (t);
  free (t);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start outputting a function.  */
/* Start outputting a function.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_function (void *p, const char *name, bfd_boolean global)
tg_start_function (void *p, const char *name, bfd_boolean global)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *dname;
  char *dname;
 
 
  if (! global)
  if (! global)
    info->stack->flavor = "static";
    info->stack->flavor = "static";
  else
  else
    info->stack->flavor = NULL;
    info->stack->flavor = NULL;
 
 
  dname = NULL;
  dname = NULL;
  if (info->demangler)
  if (info->demangler)
    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
 
 
  if (! substitute_type (info, dname ? dname : name))
  if (! substitute_type (info, dname ? dname : name))
    return FALSE;
    return FALSE;
 
 
  info->stack->method = NULL;
  info->stack->method = NULL;
  if (dname != NULL)
  if (dname != NULL)
    {
    {
      char *sep;
      char *sep;
      sep = strstr (dname, "::");
      sep = strstr (dname, "::");
      if (sep)
      if (sep)
        {
        {
          info->stack->method = dname;
          info->stack->method = dname;
          *sep = 0;
          *sep = 0;
          name = sep + 2;
          name = sep + 2;
        }
        }
      else
      else
        {
        {
          info->stack->method = "";
          info->stack->method = "";
          name = dname;
          name = dname;
        }
        }
      sep = strchr (name, '(');
      sep = strchr (name, '(');
      if (sep)
      if (sep)
        *sep = 0;
        *sep = 0;
      /* Obscure functions as type_info function.  */
      /* Obscure functions as type_info function.  */
    }
    }
 
 
  info->stack->parents = strdup (name);
  info->stack->parents = strdup (name);
 
 
  if (! info->stack->method && ! append_type (info, "("))
  if (! info->stack->method && ! append_type (info, "("))
    return FALSE;
    return FALSE;
 
 
  info->parameter = 1;
  info->parameter = 1;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a function parameter.  */
/* Output a function parameter.  */
 
 
static bfd_boolean
static bfd_boolean
tg_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
tg_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
                       bfd_vma val ATTRIBUTE_UNUSED)
                       bfd_vma val ATTRIBUTE_UNUSED)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char *t;
  char *t;
 
 
  if (kind == DEBUG_PARM_REFERENCE
  if (kind == DEBUG_PARM_REFERENCE
      || kind == DEBUG_PARM_REF_REG)
      || kind == DEBUG_PARM_REF_REG)
    {
    {
      if (! pr_reference_type (p))
      if (! pr_reference_type (p))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! substitute_type (info, name))
  if (! substitute_type (info, name))
    return FALSE;
    return FALSE;
 
 
  t = pop_type (info);
  t = pop_type (info);
  if (t == NULL)
  if (t == NULL)
    return FALSE;
    return FALSE;
 
 
  if (! info->stack->method)
  if (! info->stack->method)
    {
    {
      if (info->parameter != 1 && ! append_type (info, ", "))
      if (info->parameter != 1 && ! append_type (info, ", "))
        return FALSE;
        return FALSE;
 
 
      if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
      if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
        if (! append_type (info, "register "))
        if (! append_type (info, "register "))
          return FALSE;
          return FALSE;
 
 
      if (! append_type (info, t))
      if (! append_type (info, t))
        return FALSE;
        return FALSE;
    }
    }
 
 
  free (t);
  free (t);
 
 
  ++info->parameter;
  ++info->parameter;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start writing out a block.  */
/* Start writing out a block.  */
 
 
static bfd_boolean
static bfd_boolean
tg_start_block (void *p, bfd_vma addr)
tg_start_block (void *p, bfd_vma addr)
{
{
  struct pr_handle *info = (struct pr_handle *) p;
  struct pr_handle *info = (struct pr_handle *) p;
  char ab[20], kind, *partof;
  char ab[20], kind, *partof;
  char *t;
  char *t;
  bfd_boolean local;
  bfd_boolean local;
 
 
  if (info->parameter > 0)
  if (info->parameter > 0)
    {
    {
      info->parameter = 0;
      info->parameter = 0;
 
 
      /* Delayed name.  */
      /* Delayed name.  */
      fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
      fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
      free (info->stack->parents);
      free (info->stack->parents);
 
 
      print_vma (addr, ab, TRUE, TRUE);
      print_vma (addr, ab, TRUE, TRUE);
      translate_addresses (info->abfd, ab, info->f, info->syms);
      translate_addresses (info->abfd, ab, info->f, info->syms);
      local = info->stack->flavor != NULL;
      local = info->stack->flavor != NULL;
      if (info->stack->method && *info->stack->method)
      if (info->stack->method && *info->stack->method)
        {
        {
          kind = 'm';
          kind = 'm';
          partof = (char *) info->stack->method;
          partof = (char *) info->stack->method;
        }
        }
      else
      else
        {
        {
          kind = 'f';
          kind = 'f';
          partof = NULL;
          partof = NULL;
          if (! info->stack->method && ! append_type (info, ")"))
          if (! info->stack->method && ! append_type (info, ")"))
            return FALSE;
            return FALSE;
        }
        }
      t = pop_type (info);
      t = pop_type (info);
      if (t == NULL)
      if (t == NULL)
        return FALSE;
        return FALSE;
      fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t);
      fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t);
      if (local)
      if (local)
        fputs ("\tfile:", info->f);
        fputs ("\tfile:", info->f);
      if (partof)
      if (partof)
        {
        {
          fprintf (info->f, "\tclass:%s", partof);
          fprintf (info->f, "\tclass:%s", partof);
          free (partof);
          free (partof);
        }
        }
      fputc ('\n', info->f);
      fputc ('\n', info->f);
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out line number information.  */
/* Write out line number information.  */
 
 
static bfd_boolean
static bfd_boolean
tg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED,
tg_lineno (void *p ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED,
           unsigned long lineno ATTRIBUTE_UNUSED,
           unsigned long lineno ATTRIBUTE_UNUSED,
           bfd_vma addr ATTRIBUTE_UNUSED)
           bfd_vma addr ATTRIBUTE_UNUSED)
{
{
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish writing out a block.  */
/* Finish writing out a block.  */
 
 
static bfd_boolean
static bfd_boolean
tg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED)
tg_end_block (void *p ATTRIBUTE_UNUSED, bfd_vma addr ATTRIBUTE_UNUSED)
{
{
  return TRUE;
  return TRUE;
}
}
 
 
/* Convert the visibility value into a human readable name.  */
/* Convert the visibility value into a human readable name.  */
 
 
static const char *
static const char *
visibility_name (enum debug_visibility visibility)
visibility_name (enum debug_visibility visibility)
{
{
  const char *s;
  const char *s;
 
 
  switch (visibility)
  switch (visibility)
    {
    {
    case DEBUG_VISIBILITY_PUBLIC:
    case DEBUG_VISIBILITY_PUBLIC:
      s = "public";
      s = "public";
      break;
      break;
    case DEBUG_VISIBILITY_PRIVATE:
    case DEBUG_VISIBILITY_PRIVATE:
      s = "private";
      s = "private";
      break;
      break;
    case DEBUG_VISIBILITY_PROTECTED:
    case DEBUG_VISIBILITY_PROTECTED:
      s = "protected";
      s = "protected";
      break;
      break;
    case DEBUG_VISIBILITY_IGNORE:
    case DEBUG_VISIBILITY_IGNORE:
      s = "/* ignore */";
      s = "/* ignore */";
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      return FALSE;
      return FALSE;
    }
    }
  return s;
  return s;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.