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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [ieee.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
/* ieee.c -- Read and write IEEE-695 debugging information.
/* ieee.c -- Read and write IEEE-695 debugging information.
   Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007
   Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Ian Lance Taylor <ian@cygnus.com>.
   Written by Ian Lance Taylor <ian@cygnus.com>.
 
 
   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 reads and writes IEEE-695 debugging information.  */
/* This file reads and writes IEEE-695 debugging information.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include <assert.h>
#include <assert.h>
#include "bfd.h"
#include "bfd.h"
#include "ieee.h"
#include "ieee.h"
#include "libiberty.h"
#include "libiberty.h"
#include "debug.h"
#include "debug.h"
#include "budbg.h"
#include "budbg.h"
#include "filenames.h"
#include "filenames.h"
 
 
/* This structure holds an entry on the block stack.  */
/* This structure holds an entry on the block stack.  */
 
 
struct ieee_block
struct ieee_block
{
{
  /* The kind of block.  */
  /* The kind of block.  */
  int kind;
  int kind;
  /* The source file name, for a BB5 block.  */
  /* The source file name, for a BB5 block.  */
  const char *filename;
  const char *filename;
  /* The index of the function type, for a BB4 or BB6 block.  */
  /* The index of the function type, for a BB4 or BB6 block.  */
  unsigned int fnindx;
  unsigned int fnindx;
  /* TRUE if this function is being skipped.  */
  /* TRUE if this function is being skipped.  */
  bfd_boolean skip;
  bfd_boolean skip;
};
};
 
 
/* This structure is the block stack.  */
/* This structure is the block stack.  */
 
 
#define BLOCKSTACK_SIZE (16)
#define BLOCKSTACK_SIZE (16)
 
 
struct ieee_blockstack
struct ieee_blockstack
{
{
  /* The stack pointer.  */
  /* The stack pointer.  */
  struct ieee_block *bsp;
  struct ieee_block *bsp;
  /* The stack.  */
  /* The stack.  */
  struct ieee_block stack[BLOCKSTACK_SIZE];
  struct ieee_block stack[BLOCKSTACK_SIZE];
};
};
 
 
/* This structure holds information for a variable.  */
/* This structure holds information for a variable.  */
 
 
struct ieee_var
struct ieee_var
{
{
  /* Start of name.  */
  /* Start of name.  */
  const char *name;
  const char *name;
  /* Length of name.  */
  /* Length of name.  */
  unsigned long namlen;
  unsigned long namlen;
  /* Type.  */
  /* Type.  */
  debug_type type;
  debug_type type;
  /* Slot if we make an indirect type.  */
  /* Slot if we make an indirect type.  */
  debug_type *pslot;
  debug_type *pslot;
  /* Kind of variable or function.  */
  /* Kind of variable or function.  */
  enum
  enum
    {
    {
      IEEE_UNKNOWN,
      IEEE_UNKNOWN,
      IEEE_EXTERNAL,
      IEEE_EXTERNAL,
      IEEE_GLOBAL,
      IEEE_GLOBAL,
      IEEE_STATIC,
      IEEE_STATIC,
      IEEE_LOCAL,
      IEEE_LOCAL,
      IEEE_FUNCTION
      IEEE_FUNCTION
    } kind;
    } kind;
};
};
 
 
/* This structure holds all the variables.  */
/* This structure holds all the variables.  */
 
 
struct ieee_vars
struct ieee_vars
{
{
  /* Number of slots allocated.  */
  /* Number of slots allocated.  */
  unsigned int alloc;
  unsigned int alloc;
  /* Variables.  */
  /* Variables.  */
  struct ieee_var *vars;
  struct ieee_var *vars;
};
};
 
 
/* This structure holds information for a type.  We need this because
/* This structure holds information for a type.  We need this because
   we don't want to represent bitfields as real types.  */
   we don't want to represent bitfields as real types.  */
 
 
struct ieee_type
struct ieee_type
{
{
  /* Type.  */
  /* Type.  */
  debug_type type;
  debug_type type;
  /* Slot if this is type is referenced before it is defined.  */
  /* Slot if this is type is referenced before it is defined.  */
  debug_type *pslot;
  debug_type *pslot;
  /* Slots for arguments if we make indirect types for them.  */
  /* Slots for arguments if we make indirect types for them.  */
  debug_type *arg_slots;
  debug_type *arg_slots;
  /* If this is a bitfield, this is the size in bits.  If this is not
  /* If this is a bitfield, this is the size in bits.  If this is not
     a bitfield, this is zero.  */
     a bitfield, this is zero.  */
  unsigned long bitsize;
  unsigned long bitsize;
};
};
 
 
/* This structure holds all the type information.  */
/* This structure holds all the type information.  */
 
 
struct ieee_types
struct ieee_types
{
{
  /* Number of slots allocated.  */
  /* Number of slots allocated.  */
  unsigned int alloc;
  unsigned int alloc;
  /* Types.  */
  /* Types.  */
  struct ieee_type *types;
  struct ieee_type *types;
  /* Builtin types.  */
  /* Builtin types.  */
#define BUILTIN_TYPE_COUNT (60)
#define BUILTIN_TYPE_COUNT (60)
  debug_type builtins[BUILTIN_TYPE_COUNT];
  debug_type builtins[BUILTIN_TYPE_COUNT];
};
};
 
 
/* This structure holds a linked last of structs with their tag names,
/* This structure holds a linked last of structs with their tag names,
   so that we can convert them to C++ classes if necessary.  */
   so that we can convert them to C++ classes if necessary.  */
 
 
struct ieee_tag
struct ieee_tag
{
{
  /* Next tag.  */
  /* Next tag.  */
  struct ieee_tag *next;
  struct ieee_tag *next;
  /* This tag name.  */
  /* This tag name.  */
  const char *name;
  const char *name;
  /* The type of the tag.  */
  /* The type of the tag.  */
  debug_type type;
  debug_type type;
  /* The tagged type is an indirect type pointing at this slot.  */
  /* The tagged type is an indirect type pointing at this slot.  */
  debug_type slot;
  debug_type slot;
  /* This is an array of slots used when a field type is converted
  /* This is an array of slots used when a field type is converted
     into a indirect type, in case it needs to be later converted into
     into a indirect type, in case it needs to be later converted into
     a reference type.  */
     a reference type.  */
  debug_type *fslots;
  debug_type *fslots;
};
};
 
 
/* This structure holds the information we pass around to the parsing
/* This structure holds the information we pass around to the parsing
   functions.  */
   functions.  */
 
 
struct ieee_info
struct ieee_info
{
{
  /* The debugging handle.  */
  /* The debugging handle.  */
  void *dhandle;
  void *dhandle;
  /* The BFD.  */
  /* The BFD.  */
  bfd *abfd;
  bfd *abfd;
  /* The start of the bytes to be parsed.  */
  /* The start of the bytes to be parsed.  */
  const bfd_byte *bytes;
  const bfd_byte *bytes;
  /* The end of the bytes to be parsed.  */
  /* The end of the bytes to be parsed.  */
  const bfd_byte *pend;
  const bfd_byte *pend;
  /* The block stack.  */
  /* The block stack.  */
  struct ieee_blockstack blockstack;
  struct ieee_blockstack blockstack;
  /* Whether we have seen a BB1 or BB2.  */
  /* Whether we have seen a BB1 or BB2.  */
  bfd_boolean saw_filename;
  bfd_boolean saw_filename;
  /* The variables.  */
  /* The variables.  */
  struct ieee_vars vars;
  struct ieee_vars vars;
  /* The global variables, after a global typedef block.  */
  /* The global variables, after a global typedef block.  */
  struct ieee_vars *global_vars;
  struct ieee_vars *global_vars;
  /* The types.  */
  /* The types.  */
  struct ieee_types types;
  struct ieee_types types;
  /* The global types, after a global typedef block.  */
  /* The global types, after a global typedef block.  */
  struct ieee_types *global_types;
  struct ieee_types *global_types;
  /* The list of tagged structs.  */
  /* The list of tagged structs.  */
  struct ieee_tag *tags;
  struct ieee_tag *tags;
};
};
 
 
/* Basic builtin types, not including the pointers.  */
/* Basic builtin types, not including the pointers.  */
 
 
enum builtin_types
enum builtin_types
{
{
  builtin_unknown = 0,
  builtin_unknown = 0,
  builtin_void = 1,
  builtin_void = 1,
  builtin_signed_char = 2,
  builtin_signed_char = 2,
  builtin_unsigned_char = 3,
  builtin_unsigned_char = 3,
  builtin_signed_short_int = 4,
  builtin_signed_short_int = 4,
  builtin_unsigned_short_int = 5,
  builtin_unsigned_short_int = 5,
  builtin_signed_long = 6,
  builtin_signed_long = 6,
  builtin_unsigned_long = 7,
  builtin_unsigned_long = 7,
  builtin_signed_long_long = 8,
  builtin_signed_long_long = 8,
  builtin_unsigned_long_long = 9,
  builtin_unsigned_long_long = 9,
  builtin_float = 10,
  builtin_float = 10,
  builtin_double = 11,
  builtin_double = 11,
  builtin_long_double = 12,
  builtin_long_double = 12,
  builtin_long_long_double = 13,
  builtin_long_long_double = 13,
  builtin_quoted_string = 14,
  builtin_quoted_string = 14,
  builtin_instruction_address = 15,
  builtin_instruction_address = 15,
  builtin_int = 16,
  builtin_int = 16,
  builtin_unsigned = 17,
  builtin_unsigned = 17,
  builtin_unsigned_int = 18,
  builtin_unsigned_int = 18,
  builtin_char = 19,
  builtin_char = 19,
  builtin_long = 20,
  builtin_long = 20,
  builtin_short = 21,
  builtin_short = 21,
  builtin_unsigned_short = 22,
  builtin_unsigned_short = 22,
  builtin_short_int = 23,
  builtin_short_int = 23,
  builtin_signed_short = 24,
  builtin_signed_short = 24,
  builtin_bcd_float = 25
  builtin_bcd_float = 25
};
};
 
 
/* These are the values found in the derivation flags of a 'b'
/* These are the values found in the derivation flags of a 'b'
   component record of a 'T' type extension record in a C++ pmisc
   component record of a 'T' type extension record in a C++ pmisc
   record.  These are bitmasks.  */
   record.  These are bitmasks.  */
 
 
/* Set for a private base class, clear for a public base class.
/* Set for a private base class, clear for a public base class.
   Protected base classes are not supported.  */
   Protected base classes are not supported.  */
#define BASEFLAGS_PRIVATE (0x1)
#define BASEFLAGS_PRIVATE (0x1)
/* Set for a virtual base class.  */
/* Set for a virtual base class.  */
#define BASEFLAGS_VIRTUAL (0x2)
#define BASEFLAGS_VIRTUAL (0x2)
/* Set for a friend class, clear for a base class.  */
/* Set for a friend class, clear for a base class.  */
#define BASEFLAGS_FRIEND (0x10)
#define BASEFLAGS_FRIEND (0x10)
 
 
/* These are the values found in the specs flags of a 'd', 'm', or 'v'
/* These are the values found in the specs flags of a 'd', 'm', or 'v'
   component record of a 'T' type extension record in a C++ pmisc
   component record of a 'T' type extension record in a C++ pmisc
   record.  The same flags are used for a 'M' record in a C++ pmisc
   record.  The same flags are used for a 'M' record in a C++ pmisc
   record.  */
   record.  */
 
 
/* The lower two bits hold visibility information.  */
/* The lower two bits hold visibility information.  */
#define CXXFLAGS_VISIBILITY (0x3)
#define CXXFLAGS_VISIBILITY (0x3)
/* This value in the lower two bits indicates a public member.  */
/* This value in the lower two bits indicates a public member.  */
#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
/* This value in the lower two bits indicates a private member.  */
/* This value in the lower two bits indicates a private member.  */
#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
/* This value in the lower two bits indicates a protected member.  */
/* This value in the lower two bits indicates a protected member.  */
#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
/* Set for a static member.  */
/* Set for a static member.  */
#define CXXFLAGS_STATIC (0x4)
#define CXXFLAGS_STATIC (0x4)
/* Set for a virtual override.  */
/* Set for a virtual override.  */
#define CXXFLAGS_OVERRIDE (0x8)
#define CXXFLAGS_OVERRIDE (0x8)
/* Set for a friend function.  */
/* Set for a friend function.  */
#define CXXFLAGS_FRIEND (0x10)
#define CXXFLAGS_FRIEND (0x10)
/* Set for a const function.  */
/* Set for a const function.  */
#define CXXFLAGS_CONST (0x20)
#define CXXFLAGS_CONST (0x20)
/* Set for a volatile function.  */
/* Set for a volatile function.  */
#define CXXFLAGS_VOLATILE (0x40)
#define CXXFLAGS_VOLATILE (0x40)
/* Set for an overloaded function.  */
/* Set for an overloaded function.  */
#define CXXFLAGS_OVERLOADED (0x80)
#define CXXFLAGS_OVERLOADED (0x80)
/* Set for an operator function.  */
/* Set for an operator function.  */
#define CXXFLAGS_OPERATOR (0x100)
#define CXXFLAGS_OPERATOR (0x100)
/* Set for a constructor or destructor.  */
/* Set for a constructor or destructor.  */
#define CXXFLAGS_CTORDTOR (0x400)
#define CXXFLAGS_CTORDTOR (0x400)
/* Set for a constructor.  */
/* Set for a constructor.  */
#define CXXFLAGS_CTOR (0x200)
#define CXXFLAGS_CTOR (0x200)
/* Set for an inline function.  */
/* Set for an inline function.  */
#define CXXFLAGS_INLINE (0x800)
#define CXXFLAGS_INLINE (0x800)
 
 
/* Local functions.  */
/* Local functions.  */
 
 
static void ieee_error (struct ieee_info *, const bfd_byte *, const char *);
static void ieee_error (struct ieee_info *, const bfd_byte *, const char *);
static void ieee_eof (struct ieee_info *);
static void ieee_eof (struct ieee_info *);
static char *savestring (const char *, unsigned long);
static char *savestring (const char *, unsigned long);
static bfd_boolean ieee_read_number
static bfd_boolean ieee_read_number
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
static bfd_boolean ieee_read_optional_number
static bfd_boolean ieee_read_optional_number
  (struct ieee_info *, const bfd_byte **, bfd_vma *, bfd_boolean *);
  (struct ieee_info *, const bfd_byte **, bfd_vma *, bfd_boolean *);
static bfd_boolean ieee_read_id
static bfd_boolean ieee_read_id
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
static bfd_boolean ieee_read_optional_id
static bfd_boolean ieee_read_optional_id
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *,
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *,
   bfd_boolean *);
   bfd_boolean *);
static bfd_boolean ieee_read_expression
static bfd_boolean ieee_read_expression
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
static debug_type ieee_builtin_type
static debug_type ieee_builtin_type
  (struct ieee_info *, const bfd_byte *, unsigned int);
  (struct ieee_info *, const bfd_byte *, unsigned int);
static bfd_boolean ieee_alloc_type
static bfd_boolean ieee_alloc_type
  (struct ieee_info *, unsigned int, bfd_boolean);
  (struct ieee_info *, unsigned int, bfd_boolean);
static bfd_boolean ieee_read_type_index
static bfd_boolean ieee_read_type_index
  (struct ieee_info *, const bfd_byte **, debug_type *);
  (struct ieee_info *, const bfd_byte **, debug_type *);
static int ieee_regno_to_genreg (bfd *, int);
static int ieee_regno_to_genreg (bfd *, int);
static int ieee_genreg_to_regno (bfd *, int);
static int ieee_genreg_to_regno (bfd *, int);
static bfd_boolean parse_ieee_bb (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_bb (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_be (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_be (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_nn (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_nn (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_ty (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_ty (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_atn (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_atn (struct ieee_info *, const bfd_byte **);
static bfd_boolean ieee_read_cxx_misc
static bfd_boolean ieee_read_cxx_misc
  (struct ieee_info *, const bfd_byte **, unsigned long);
  (struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_cxx_class
static bfd_boolean ieee_read_cxx_class
  (struct ieee_info *, const bfd_byte **, unsigned long);
  (struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_cxx_defaults
static bfd_boolean ieee_read_cxx_defaults
  (struct ieee_info *, const bfd_byte **, unsigned long);
  (struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_reference
static bfd_boolean ieee_read_reference
  (struct ieee_info *, const bfd_byte **);
  (struct ieee_info *, const bfd_byte **);
static bfd_boolean ieee_require_asn
static bfd_boolean ieee_require_asn
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
  (struct ieee_info *, const bfd_byte **, bfd_vma *);
static bfd_boolean ieee_require_atn65
static bfd_boolean ieee_require_atn65
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
  (struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
 
 
/* Report an error in the IEEE debugging information.  */
/* Report an error in the IEEE debugging information.  */
 
 
static void
static void
ieee_error (struct ieee_info *info, const bfd_byte *p, const char *s)
ieee_error (struct ieee_info *info, const bfd_byte *p, const char *s)
{
{
  if (p != NULL)
  if (p != NULL)
    fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
    fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
             (unsigned long) (p - info->bytes), s, *p);
             (unsigned long) (p - info->bytes), s, *p);
  else
  else
    fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
    fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
}
}
 
 
/* Report an unexpected EOF in the IEEE debugging information.  */
/* Report an unexpected EOF in the IEEE debugging information.  */
 
 
static void
static void
ieee_eof (struct ieee_info *info)
ieee_eof (struct ieee_info *info)
{
{
  ieee_error (info, (const bfd_byte *) NULL,
  ieee_error (info, (const bfd_byte *) NULL,
              _("unexpected end of debugging information"));
              _("unexpected end of debugging information"));
}
}
 
 
/* Save a string in memory.  */
/* Save a string in memory.  */
 
 
static char *
static char *
savestring (const char *start, unsigned long len)
savestring (const char *start, unsigned long len)
{
{
  char *ret;
  char *ret;
 
 
  ret = (char *) xmalloc (len + 1);
  ret = (char *) xmalloc (len + 1);
  memcpy (ret, start, len);
  memcpy (ret, start, len);
  ret[len] = '\0';
  ret[len] = '\0';
  return ret;
  return ret;
}
}
 
 
/* Read a number which must be present in an IEEE file.  */
/* Read a number which must be present in an IEEE file.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_number (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
ieee_read_number (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
{
{
  return ieee_read_optional_number (info, pp, pv, (bfd_boolean *) NULL);
  return ieee_read_optional_number (info, pp, pv, (bfd_boolean *) NULL);
}
}
 
 
/* Read a number in an IEEE file.  If ppresent is not NULL, the number
/* Read a number in an IEEE file.  If ppresent is not NULL, the number
   need not be there.  */
   need not be there.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_optional_number (struct ieee_info *info, const bfd_byte **pp,
ieee_read_optional_number (struct ieee_info *info, const bfd_byte **pp,
                           bfd_vma *pv, bfd_boolean *ppresent)
                           bfd_vma *pv, bfd_boolean *ppresent)
{
{
  ieee_record_enum_type b;
  ieee_record_enum_type b;
 
 
  if (*pp >= info->pend)
  if (*pp >= info->pend)
    {
    {
      if (ppresent != NULL)
      if (ppresent != NULL)
        {
        {
          *ppresent = FALSE;
          *ppresent = FALSE;
          return TRUE;
          return TRUE;
        }
        }
      ieee_eof (info);
      ieee_eof (info);
      return FALSE;
      return FALSE;
    }
    }
 
 
  b = (ieee_record_enum_type) **pp;
  b = (ieee_record_enum_type) **pp;
  ++*pp;
  ++*pp;
 
 
  if (b <= ieee_number_end_enum)
  if (b <= ieee_number_end_enum)
    {
    {
      *pv = (bfd_vma) b;
      *pv = (bfd_vma) b;
      if (ppresent != NULL)
      if (ppresent != NULL)
        *ppresent = TRUE;
        *ppresent = TRUE;
      return TRUE;
      return TRUE;
    }
    }
 
 
  if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
  if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
    {
    {
      unsigned int i;
      unsigned int i;
 
 
      i = (int) b - (int) ieee_number_repeat_start_enum;
      i = (int) b - (int) ieee_number_repeat_start_enum;
      if (*pp + i - 1 >= info->pend)
      if (*pp + i - 1 >= info->pend)
        {
        {
          ieee_eof (info);
          ieee_eof (info);
          return FALSE;
          return FALSE;
        }
        }
 
 
      *pv = 0;
      *pv = 0;
      for (; i > 0; i--)
      for (; i > 0; i--)
        {
        {
          *pv <<= 8;
          *pv <<= 8;
          *pv += **pp;
          *pv += **pp;
          ++*pp;
          ++*pp;
        }
        }
 
 
      if (ppresent != NULL)
      if (ppresent != NULL)
        *ppresent = TRUE;
        *ppresent = TRUE;
 
 
      return TRUE;
      return TRUE;
    }
    }
 
 
  if (ppresent != NULL)
  if (ppresent != NULL)
    {
    {
      --*pp;
      --*pp;
      *ppresent = FALSE;
      *ppresent = FALSE;
      return TRUE;
      return TRUE;
    }
    }
 
 
  ieee_error (info, *pp - 1, _("invalid number"));
  ieee_error (info, *pp - 1, _("invalid number"));
  return FALSE;
  return FALSE;
}
}
 
 
/* Read a required string from an IEEE file.  */
/* Read a required string from an IEEE file.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_id (struct ieee_info *info, const bfd_byte **pp,
ieee_read_id (struct ieee_info *info, const bfd_byte **pp,
              const char **pname, unsigned long *pnamlen)
              const char **pname, unsigned long *pnamlen)
{
{
  return ieee_read_optional_id (info, pp, pname, pnamlen, (bfd_boolean *) NULL);
  return ieee_read_optional_id (info, pp, pname, pnamlen, (bfd_boolean *) NULL);
}
}
 
 
/* Read a string from an IEEE file.  If ppresent is not NULL, the
/* Read a string from an IEEE file.  If ppresent is not NULL, the
   string is optional.  */
   string is optional.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_optional_id (struct ieee_info *info, const bfd_byte **pp,
ieee_read_optional_id (struct ieee_info *info, const bfd_byte **pp,
                       const char **pname, unsigned long *pnamlen,
                       const char **pname, unsigned long *pnamlen,
                       bfd_boolean *ppresent)
                       bfd_boolean *ppresent)
{
{
  bfd_byte b;
  bfd_byte b;
  unsigned long len;
  unsigned long len;
 
 
  if (*pp >= info->pend)
  if (*pp >= info->pend)
    {
    {
      ieee_eof (info);
      ieee_eof (info);
      return FALSE;
      return FALSE;
    }
    }
 
 
  b = **pp;
  b = **pp;
  ++*pp;
  ++*pp;
 
 
  if (b <= 0x7f)
  if (b <= 0x7f)
    len = b;
    len = b;
  else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
  else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
    {
    {
      len = **pp;
      len = **pp;
      ++*pp;
      ++*pp;
    }
    }
  else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
  else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
    {
    {
      len = (**pp << 8) + (*pp)[1];
      len = (**pp << 8) + (*pp)[1];
      *pp += 2;
      *pp += 2;
    }
    }
  else
  else
    {
    {
      if (ppresent != NULL)
      if (ppresent != NULL)
        {
        {
          --*pp;
          --*pp;
          *ppresent = FALSE;
          *ppresent = FALSE;
          return TRUE;
          return TRUE;
        }
        }
      ieee_error (info, *pp - 1, _("invalid string length"));
      ieee_error (info, *pp - 1, _("invalid string length"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  if ((unsigned long) (info->pend - *pp) < len)
  if ((unsigned long) (info->pend - *pp) < len)
    {
    {
      ieee_eof (info);
      ieee_eof (info);
      return FALSE;
      return FALSE;
    }
    }
 
 
  *pname = (const char *) *pp;
  *pname = (const char *) *pp;
  *pnamlen = len;
  *pnamlen = len;
  *pp += len;
  *pp += len;
 
 
  if (ppresent != NULL)
  if (ppresent != NULL)
    *ppresent = TRUE;
    *ppresent = TRUE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Read an expression from an IEEE file.  Since this code is only used
/* Read an expression from an IEEE file.  Since this code is only used
   to parse debugging information, I haven't bothered to write a full
   to parse debugging information, I haven't bothered to write a full
   blown IEEE expression parser.  I've only thrown in the things I've
   blown IEEE expression parser.  I've only thrown in the things I've
   seen in debugging information.  This can be easily extended if
   seen in debugging information.  This can be easily extended if
   necessary.  */
   necessary.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_expression (struct ieee_info *info, const bfd_byte **pp,
ieee_read_expression (struct ieee_info *info, const bfd_byte **pp,
                      bfd_vma *pv)
                      bfd_vma *pv)
{
{
  const bfd_byte *expr_start;
  const bfd_byte *expr_start;
#define EXPR_STACK_SIZE (10)
#define EXPR_STACK_SIZE (10)
  bfd_vma expr_stack[EXPR_STACK_SIZE];
  bfd_vma expr_stack[EXPR_STACK_SIZE];
  bfd_vma *esp;
  bfd_vma *esp;
 
 
  expr_start = *pp;
  expr_start = *pp;
 
 
  esp = expr_stack;
  esp = expr_stack;
 
 
  while (1)
  while (1)
    {
    {
      const bfd_byte *start;
      const bfd_byte *start;
      bfd_vma val;
      bfd_vma val;
      bfd_boolean present;
      bfd_boolean present;
      ieee_record_enum_type c;
      ieee_record_enum_type c;
 
 
      start = *pp;
      start = *pp;
 
 
      if (! ieee_read_optional_number (info, pp, &val, &present))
      if (! ieee_read_optional_number (info, pp, &val, &present))
        return FALSE;
        return FALSE;
 
 
      if (present)
      if (present)
        {
        {
          if (esp - expr_stack >= EXPR_STACK_SIZE)
          if (esp - expr_stack >= EXPR_STACK_SIZE)
            {
            {
              ieee_error (info, start, _("expression stack overflow"));
              ieee_error (info, start, _("expression stack overflow"));
              return FALSE;
              return FALSE;
            }
            }
          *esp++ = val;
          *esp++ = val;
          continue;
          continue;
        }
        }
 
 
      c = (ieee_record_enum_type) **pp;
      c = (ieee_record_enum_type) **pp;
 
 
      if (c >= ieee_module_beginning_enum)
      if (c >= ieee_module_beginning_enum)
        break;
        break;
 
 
      ++*pp;
      ++*pp;
 
 
      if (c == ieee_comma)
      if (c == ieee_comma)
        break;
        break;
 
 
      switch (c)
      switch (c)
        {
        {
        default:
        default:
          ieee_error (info, start, _("unsupported IEEE expression operator"));
          ieee_error (info, start, _("unsupported IEEE expression operator"));
          break;
          break;
 
 
        case ieee_variable_R_enum:
        case ieee_variable_R_enum:
          {
          {
            bfd_vma indx;
            bfd_vma indx;
            asection *s;
            asection *s;
 
 
            if (! ieee_read_number (info, pp, &indx))
            if (! ieee_read_number (info, pp, &indx))
              return FALSE;
              return FALSE;
            for (s = info->abfd->sections; s != NULL; s = s->next)
            for (s = info->abfd->sections; s != NULL; s = s->next)
              if ((bfd_vma) s->target_index == indx)
              if ((bfd_vma) s->target_index == indx)
                break;
                break;
            if (s == NULL)
            if (s == NULL)
              {
              {
                ieee_error (info, start, _("unknown section"));
                ieee_error (info, start, _("unknown section"));
                return FALSE;
                return FALSE;
              }
              }
 
 
            if (esp - expr_stack >= EXPR_STACK_SIZE)
            if (esp - expr_stack >= EXPR_STACK_SIZE)
              {
              {
                ieee_error (info, start, _("expression stack overflow"));
                ieee_error (info, start, _("expression stack overflow"));
                return FALSE;
                return FALSE;
              }
              }
 
 
            *esp++ = bfd_get_section_vma (info->abfd, s);
            *esp++ = bfd_get_section_vma (info->abfd, s);
          }
          }
          break;
          break;
 
 
        case ieee_function_plus_enum:
        case ieee_function_plus_enum:
        case ieee_function_minus_enum:
        case ieee_function_minus_enum:
          {
          {
            bfd_vma v1, v2;
            bfd_vma v1, v2;
 
 
            if (esp - expr_stack < 2)
            if (esp - expr_stack < 2)
              {
              {
                ieee_error (info, start, _("expression stack underflow"));
                ieee_error (info, start, _("expression stack underflow"));
                return FALSE;
                return FALSE;
              }
              }
 
 
            v1 = *--esp;
            v1 = *--esp;
            v2 = *--esp;
            v2 = *--esp;
            *esp++ = v1 + v2;
            *esp++ = v1 + v2;
          }
          }
          break;
          break;
        }
        }
    }
    }
 
 
  if (esp - 1 != expr_stack)
  if (esp - 1 != expr_stack)
    {
    {
      ieee_error (info, expr_start, _("expression stack mismatch"));
      ieee_error (info, expr_start, _("expression stack mismatch"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  *pv = *--esp;
  *pv = *--esp;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Return an IEEE builtin type.  */
/* Return an IEEE builtin type.  */
 
 
static debug_type
static debug_type
ieee_builtin_type (struct ieee_info *info, const bfd_byte *p,
ieee_builtin_type (struct ieee_info *info, const bfd_byte *p,
                   unsigned int indx)
                   unsigned int indx)
{
{
  void *dhandle;
  void *dhandle;
  debug_type type;
  debug_type type;
  const char *name;
  const char *name;
 
 
  if (indx < BUILTIN_TYPE_COUNT
  if (indx < BUILTIN_TYPE_COUNT
      && info->types.builtins[indx] != DEBUG_TYPE_NULL)
      && info->types.builtins[indx] != DEBUG_TYPE_NULL)
    return info->types.builtins[indx];
    return info->types.builtins[indx];
 
 
  dhandle = info->dhandle;
  dhandle = info->dhandle;
 
 
  if (indx >= 32 && indx < 64)
  if (indx >= 32 && indx < 64)
    {
    {
      type = debug_make_pointer_type (dhandle,
      type = debug_make_pointer_type (dhandle,
                                      ieee_builtin_type (info, p, indx - 32));
                                      ieee_builtin_type (info, p, indx - 32));
      assert (indx < BUILTIN_TYPE_COUNT);
      assert (indx < BUILTIN_TYPE_COUNT);
      info->types.builtins[indx] = type;
      info->types.builtins[indx] = type;
      return type;
      return type;
    }
    }
 
 
  switch ((enum builtin_types) indx)
  switch ((enum builtin_types) indx)
    {
    {
    default:
    default:
      ieee_error (info, p, _("unknown builtin type"));
      ieee_error (info, p, _("unknown builtin type"));
      return NULL;
      return NULL;
 
 
    case builtin_unknown:
    case builtin_unknown:
      type = debug_make_void_type (dhandle);
      type = debug_make_void_type (dhandle);
      name = NULL;
      name = NULL;
      break;
      break;
 
 
    case builtin_void:
    case builtin_void:
      type = debug_make_void_type (dhandle);
      type = debug_make_void_type (dhandle);
      name = "void";
      name = "void";
      break;
      break;
 
 
    case builtin_signed_char:
    case builtin_signed_char:
      type = debug_make_int_type (dhandle, 1, FALSE);
      type = debug_make_int_type (dhandle, 1, FALSE);
      name = "signed char";
      name = "signed char";
      break;
      break;
 
 
    case builtin_unsigned_char:
    case builtin_unsigned_char:
      type = debug_make_int_type (dhandle, 1, TRUE);
      type = debug_make_int_type (dhandle, 1, TRUE);
      name = "unsigned char";
      name = "unsigned char";
      break;
      break;
 
 
    case builtin_signed_short_int:
    case builtin_signed_short_int:
      type = debug_make_int_type (dhandle, 2, FALSE);
      type = debug_make_int_type (dhandle, 2, FALSE);
      name = "signed short int";
      name = "signed short int";
      break;
      break;
 
 
    case builtin_unsigned_short_int:
    case builtin_unsigned_short_int:
      type = debug_make_int_type (dhandle, 2, TRUE);
      type = debug_make_int_type (dhandle, 2, TRUE);
      name = "unsigned short int";
      name = "unsigned short int";
      break;
      break;
 
 
    case builtin_signed_long:
    case builtin_signed_long:
      type = debug_make_int_type (dhandle, 4, FALSE);
      type = debug_make_int_type (dhandle, 4, FALSE);
      name = "signed long";
      name = "signed long";
      break;
      break;
 
 
    case builtin_unsigned_long:
    case builtin_unsigned_long:
      type = debug_make_int_type (dhandle, 4, TRUE);
      type = debug_make_int_type (dhandle, 4, TRUE);
      name = "unsigned long";
      name = "unsigned long";
      break;
      break;
 
 
    case builtin_signed_long_long:
    case builtin_signed_long_long:
      type = debug_make_int_type (dhandle, 8, FALSE);
      type = debug_make_int_type (dhandle, 8, FALSE);
      name = "signed long long";
      name = "signed long long";
      break;
      break;
 
 
    case builtin_unsigned_long_long:
    case builtin_unsigned_long_long:
      type = debug_make_int_type (dhandle, 8, TRUE);
      type = debug_make_int_type (dhandle, 8, TRUE);
      name = "unsigned long long";
      name = "unsigned long long";
      break;
      break;
 
 
    case builtin_float:
    case builtin_float:
      type = debug_make_float_type (dhandle, 4);
      type = debug_make_float_type (dhandle, 4);
      name = "float";
      name = "float";
      break;
      break;
 
 
    case builtin_double:
    case builtin_double:
      type = debug_make_float_type (dhandle, 8);
      type = debug_make_float_type (dhandle, 8);
      name = "double";
      name = "double";
      break;
      break;
 
 
    case builtin_long_double:
    case builtin_long_double:
      /* FIXME: The size for this type should depend upon the
      /* FIXME: The size for this type should depend upon the
         processor.  */
         processor.  */
      type = debug_make_float_type (dhandle, 12);
      type = debug_make_float_type (dhandle, 12);
      name = "long double";
      name = "long double";
      break;
      break;
 
 
    case builtin_long_long_double:
    case builtin_long_long_double:
      type = debug_make_float_type (dhandle, 16);
      type = debug_make_float_type (dhandle, 16);
      name = "long long double";
      name = "long long double";
      break;
      break;
 
 
    case builtin_quoted_string:
    case builtin_quoted_string:
      type = debug_make_array_type (dhandle,
      type = debug_make_array_type (dhandle,
                                    ieee_builtin_type (info, p,
                                    ieee_builtin_type (info, p,
                                                       ((unsigned int)
                                                       ((unsigned int)
                                                        builtin_char)),
                                                        builtin_char)),
                                    ieee_builtin_type (info, p,
                                    ieee_builtin_type (info, p,
                                                       ((unsigned int)
                                                       ((unsigned int)
                                                        builtin_int)),
                                                        builtin_int)),
                                    0, -1, TRUE);
                                    0, -1, TRUE);
      name = "QUOTED STRING";
      name = "QUOTED STRING";
      break;
      break;
 
 
    case builtin_instruction_address:
    case builtin_instruction_address:
      /* FIXME: This should be a code address.  */
      /* FIXME: This should be a code address.  */
      type = debug_make_int_type (dhandle, 4, TRUE);
      type = debug_make_int_type (dhandle, 4, TRUE);
      name = "instruction address";
      name = "instruction address";
      break;
      break;
 
 
    case builtin_int:
    case builtin_int:
      /* FIXME: The size for this type should depend upon the
      /* FIXME: The size for this type should depend upon the
         processor.  */
         processor.  */
      type = debug_make_int_type (dhandle, 4, FALSE);
      type = debug_make_int_type (dhandle, 4, FALSE);
      name = "int";
      name = "int";
      break;
      break;
 
 
    case builtin_unsigned:
    case builtin_unsigned:
      /* FIXME: The size for this type should depend upon the
      /* FIXME: The size for this type should depend upon the
         processor.  */
         processor.  */
      type = debug_make_int_type (dhandle, 4, TRUE);
      type = debug_make_int_type (dhandle, 4, TRUE);
      name = "unsigned";
      name = "unsigned";
      break;
      break;
 
 
    case builtin_unsigned_int:
    case builtin_unsigned_int:
      /* FIXME: The size for this type should depend upon the
      /* FIXME: The size for this type should depend upon the
         processor.  */
         processor.  */
      type = debug_make_int_type (dhandle, 4, TRUE);
      type = debug_make_int_type (dhandle, 4, TRUE);
      name = "unsigned int";
      name = "unsigned int";
      break;
      break;
 
 
    case builtin_char:
    case builtin_char:
      type = debug_make_int_type (dhandle, 1, FALSE);
      type = debug_make_int_type (dhandle, 1, FALSE);
      name = "char";
      name = "char";
      break;
      break;
 
 
    case builtin_long:
    case builtin_long:
      type = debug_make_int_type (dhandle, 4, FALSE);
      type = debug_make_int_type (dhandle, 4, FALSE);
      name = "long";
      name = "long";
      break;
      break;
 
 
    case builtin_short:
    case builtin_short:
      type = debug_make_int_type (dhandle, 2, FALSE);
      type = debug_make_int_type (dhandle, 2, FALSE);
      name = "short";
      name = "short";
      break;
      break;
 
 
    case builtin_unsigned_short:
    case builtin_unsigned_short:
      type = debug_make_int_type (dhandle, 2, TRUE);
      type = debug_make_int_type (dhandle, 2, TRUE);
      name = "unsigned short";
      name = "unsigned short";
      break;
      break;
 
 
    case builtin_short_int:
    case builtin_short_int:
      type = debug_make_int_type (dhandle, 2, FALSE);
      type = debug_make_int_type (dhandle, 2, FALSE);
      name = "short int";
      name = "short int";
      break;
      break;
 
 
    case builtin_signed_short:
    case builtin_signed_short:
      type = debug_make_int_type (dhandle, 2, FALSE);
      type = debug_make_int_type (dhandle, 2, FALSE);
      name = "signed short";
      name = "signed short";
      break;
      break;
 
 
    case builtin_bcd_float:
    case builtin_bcd_float:
      ieee_error (info, p, _("BCD float type not supported"));
      ieee_error (info, p, _("BCD float type not supported"));
      return DEBUG_TYPE_NULL;
      return DEBUG_TYPE_NULL;
    }
    }
 
 
  if (name != NULL)
  if (name != NULL)
    type = debug_name_type (dhandle, name, type);
    type = debug_name_type (dhandle, name, type);
 
 
  assert (indx < BUILTIN_TYPE_COUNT);
  assert (indx < BUILTIN_TYPE_COUNT);
 
 
  info->types.builtins[indx] = type;
  info->types.builtins[indx] = type;
 
 
  return type;
  return type;
}
}
 
 
/* Allocate more space in the type table.  If ref is TRUE, this is a
/* Allocate more space in the type table.  If ref is TRUE, this is a
   reference to the type; if it is not already defined, we should set
   reference to the type; if it is not already defined, we should set
   up an indirect type.  */
   up an indirect type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_alloc_type (struct ieee_info *info, unsigned int indx, bfd_boolean ref)
ieee_alloc_type (struct ieee_info *info, unsigned int indx, bfd_boolean ref)
{
{
  unsigned int nalloc;
  unsigned int nalloc;
  register struct ieee_type *t;
  register struct ieee_type *t;
  struct ieee_type *tend;
  struct ieee_type *tend;
 
 
  if (indx >= info->types.alloc)
  if (indx >= info->types.alloc)
    {
    {
      nalloc = info->types.alloc;
      nalloc = info->types.alloc;
      if (nalloc == 0)
      if (nalloc == 0)
        nalloc = 4;
        nalloc = 4;
      while (indx >= nalloc)
      while (indx >= nalloc)
        nalloc *= 2;
        nalloc *= 2;
 
 
      info->types.types = ((struct ieee_type *)
      info->types.types = ((struct ieee_type *)
                           xrealloc (info->types.types,
                           xrealloc (info->types.types,
                                     nalloc * sizeof *info->types.types));
                                     nalloc * sizeof *info->types.types));
 
 
      memset (info->types.types + info->types.alloc, 0,
      memset (info->types.types + info->types.alloc, 0,
              (nalloc - info->types.alloc) * sizeof *info->types.types);
              (nalloc - info->types.alloc) * sizeof *info->types.types);
 
 
      tend = info->types.types + nalloc;
      tend = info->types.types + nalloc;
      for (t = info->types.types + info->types.alloc; t < tend; t++)
      for (t = info->types.types + info->types.alloc; t < tend; t++)
        t->type = DEBUG_TYPE_NULL;
        t->type = DEBUG_TYPE_NULL;
 
 
      info->types.alloc = nalloc;
      info->types.alloc = nalloc;
    }
    }
 
 
  if (ref)
  if (ref)
    {
    {
      t = info->types.types + indx;
      t = info->types.types + indx;
      if (t->type == NULL)
      if (t->type == NULL)
        {
        {
          t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
          t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
          *t->pslot = DEBUG_TYPE_NULL;
          *t->pslot = DEBUG_TYPE_NULL;
          t->type = debug_make_indirect_type (info->dhandle, t->pslot,
          t->type = debug_make_indirect_type (info->dhandle, t->pslot,
                                              (const char *) NULL);
                                              (const char *) NULL);
          if (t->type == NULL)
          if (t->type == NULL)
            return FALSE;
            return FALSE;
        }
        }
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Read a type index and return the corresponding type.  */
/* Read a type index and return the corresponding type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_type_index (struct ieee_info *info, const bfd_byte **pp,
ieee_read_type_index (struct ieee_info *info, const bfd_byte **pp,
                      debug_type *ptype)
                      debug_type *ptype)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  bfd_vma indx;
  bfd_vma indx;
 
 
  start = *pp;
  start = *pp;
 
 
  if (! ieee_read_number (info, pp, &indx))
  if (! ieee_read_number (info, pp, &indx))
    return FALSE;
    return FALSE;
 
 
  if (indx < 256)
  if (indx < 256)
    {
    {
      *ptype = ieee_builtin_type (info, start, indx);
      *ptype = ieee_builtin_type (info, start, indx);
      if (*ptype == NULL)
      if (*ptype == NULL)
        return FALSE;
        return FALSE;
      return TRUE;
      return TRUE;
    }
    }
 
 
  indx -= 256;
  indx -= 256;
  if (! ieee_alloc_type (info, indx, TRUE))
  if (! ieee_alloc_type (info, indx, TRUE))
    return FALSE;
    return FALSE;
 
 
  *ptype = info->types.types[indx].type;
  *ptype = info->types.types[indx].type;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Parse IEEE debugging information for a file.  This is passed the
/* Parse IEEE debugging information for a file.  This is passed the
   bytes which compose the Debug Information Part of an IEEE file.  */
   bytes which compose the Debug Information Part of an IEEE file.  */
 
 
bfd_boolean
bfd_boolean
parse_ieee (void *dhandle, bfd *abfd, const bfd_byte *bytes, bfd_size_type len)
parse_ieee (void *dhandle, bfd *abfd, const bfd_byte *bytes, bfd_size_type len)
{
{
  struct ieee_info info;
  struct ieee_info info;
  unsigned int i;
  unsigned int i;
  const bfd_byte *p, *pend;
  const bfd_byte *p, *pend;
 
 
  info.dhandle = dhandle;
  info.dhandle = dhandle;
  info.abfd = abfd;
  info.abfd = abfd;
  info.bytes = bytes;
  info.bytes = bytes;
  info.pend = bytes + len;
  info.pend = bytes + len;
  info.blockstack.bsp = info.blockstack.stack;
  info.blockstack.bsp = info.blockstack.stack;
  info.saw_filename = FALSE;
  info.saw_filename = FALSE;
  info.vars.alloc = 0;
  info.vars.alloc = 0;
  info.vars.vars = NULL;
  info.vars.vars = NULL;
  info.global_vars = NULL;
  info.global_vars = NULL;
  info.types.alloc = 0;
  info.types.alloc = 0;
  info.types.types = NULL;
  info.types.types = NULL;
  info.global_types = NULL;
  info.global_types = NULL;
  info.tags = NULL;
  info.tags = NULL;
  for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
  for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
    info.types.builtins[i] = DEBUG_TYPE_NULL;
    info.types.builtins[i] = DEBUG_TYPE_NULL;
 
 
  p = bytes;
  p = bytes;
  pend = info.pend;
  pend = info.pend;
  while (p < pend)
  while (p < pend)
    {
    {
      const bfd_byte *record_start;
      const bfd_byte *record_start;
      ieee_record_enum_type c;
      ieee_record_enum_type c;
 
 
      record_start = p;
      record_start = p;
 
 
      c = (ieee_record_enum_type) *p++;
      c = (ieee_record_enum_type) *p++;
 
 
      if (c == ieee_at_record_enum)
      if (c == ieee_at_record_enum)
        c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
        c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
 
 
      if (c <= ieee_number_repeat_end_enum)
      if (c <= ieee_number_repeat_end_enum)
        {
        {
          ieee_error (&info, record_start, _("unexpected number"));
          ieee_error (&info, record_start, _("unexpected number"));
          return FALSE;
          return FALSE;
        }
        }
 
 
      switch (c)
      switch (c)
        {
        {
        default:
        default:
          ieee_error (&info, record_start, _("unexpected record type"));
          ieee_error (&info, record_start, _("unexpected record type"));
          return FALSE;
          return FALSE;
 
 
        case ieee_bb_record_enum:
        case ieee_bb_record_enum:
          if (! parse_ieee_bb (&info, &p))
          if (! parse_ieee_bb (&info, &p))
            return FALSE;
            return FALSE;
          break;
          break;
 
 
        case ieee_be_record_enum:
        case ieee_be_record_enum:
          if (! parse_ieee_be (&info, &p))
          if (! parse_ieee_be (&info, &p))
            return FALSE;
            return FALSE;
          break;
          break;
 
 
        case ieee_nn_record:
        case ieee_nn_record:
          if (! parse_ieee_nn (&info, &p))
          if (! parse_ieee_nn (&info, &p))
            return FALSE;
            return FALSE;
          break;
          break;
 
 
        case ieee_ty_record_enum:
        case ieee_ty_record_enum:
          if (! parse_ieee_ty (&info, &p))
          if (! parse_ieee_ty (&info, &p))
            return FALSE;
            return FALSE;
          break;
          break;
 
 
        case ieee_atn_record_enum:
        case ieee_atn_record_enum:
          if (! parse_ieee_atn (&info, &p))
          if (! parse_ieee_atn (&info, &p))
            return FALSE;
            return FALSE;
          break;
          break;
        }
        }
    }
    }
 
 
  if (info.blockstack.bsp != info.blockstack.stack)
  if (info.blockstack.bsp != info.blockstack.stack)
    {
    {
      ieee_error (&info, (const bfd_byte *) NULL,
      ieee_error (&info, (const bfd_byte *) NULL,
                  _("blocks left on stack at end"));
                  _("blocks left on stack at end"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Handle an IEEE BB record.  */
/* Handle an IEEE BB record.  */
 
 
static bfd_boolean
static bfd_boolean
parse_ieee_bb (struct ieee_info *info, const bfd_byte **pp)
parse_ieee_bb (struct ieee_info *info, const bfd_byte **pp)
{
{
  const bfd_byte *block_start;
  const bfd_byte *block_start;
  bfd_byte b;
  bfd_byte b;
  bfd_vma size;
  bfd_vma size;
  const char *name;
  const char *name;
  unsigned long namlen;
  unsigned long namlen;
  char *namcopy = NULL;
  char *namcopy = NULL;
  unsigned int fnindx;
  unsigned int fnindx;
  bfd_boolean skip;
  bfd_boolean skip;
 
 
  block_start = *pp;
  block_start = *pp;
 
 
  b = **pp;
  b = **pp;
  ++*pp;
  ++*pp;
 
 
  if (! ieee_read_number (info, pp, &size)
  if (! ieee_read_number (info, pp, &size)
      || ! ieee_read_id (info, pp, &name, &namlen))
      || ! ieee_read_id (info, pp, &name, &namlen))
    return FALSE;
    return FALSE;
 
 
  fnindx = (unsigned int) -1;
  fnindx = (unsigned int) -1;
  skip = FALSE;
  skip = FALSE;
 
 
  switch (b)
  switch (b)
    {
    {
    case 1:
    case 1:
      /* BB1: Type definitions local to a module.  */
      /* BB1: Type definitions local to a module.  */
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (namcopy == NULL)
      if (namcopy == NULL)
        return FALSE;
        return FALSE;
      if (! debug_set_filename (info->dhandle, namcopy))
      if (! debug_set_filename (info->dhandle, namcopy))
        return FALSE;
        return FALSE;
      info->saw_filename = TRUE;
      info->saw_filename = TRUE;
 
 
      /* Discard any variables or types we may have seen before.  */
      /* Discard any variables or types we may have seen before.  */
      if (info->vars.vars != NULL)
      if (info->vars.vars != NULL)
        free (info->vars.vars);
        free (info->vars.vars);
      info->vars.vars = NULL;
      info->vars.vars = NULL;
      info->vars.alloc = 0;
      info->vars.alloc = 0;
      if (info->types.types != NULL)
      if (info->types.types != NULL)
        free (info->types.types);
        free (info->types.types);
      info->types.types = NULL;
      info->types.types = NULL;
      info->types.alloc = 0;
      info->types.alloc = 0;
 
 
      /* Initialize the types to the global types.  */
      /* Initialize the types to the global types.  */
      if (info->global_types != NULL)
      if (info->global_types != NULL)
        {
        {
          info->types.alloc = info->global_types->alloc;
          info->types.alloc = info->global_types->alloc;
          info->types.types = ((struct ieee_type *)
          info->types.types = ((struct ieee_type *)
                               xmalloc (info->types.alloc
                               xmalloc (info->types.alloc
                                        * sizeof (*info->types.types)));
                                        * sizeof (*info->types.types)));
          memcpy (info->types.types, info->global_types->types,
          memcpy (info->types.types, info->global_types->types,
                  info->types.alloc * sizeof (*info->types.types));
                  info->types.alloc * sizeof (*info->types.types));
        }
        }
 
 
      break;
      break;
 
 
    case 2:
    case 2:
      /* BB2: Global type definitions.  The name is supposed to be
      /* BB2: Global type definitions.  The name is supposed to be
         empty, but we don't check.  */
         empty, but we don't check.  */
      if (! debug_set_filename (info->dhandle, "*global*"))
      if (! debug_set_filename (info->dhandle, "*global*"))
        return FALSE;
        return FALSE;
      info->saw_filename = TRUE;
      info->saw_filename = TRUE;
      break;
      break;
 
 
    case 3:
    case 3:
      /* BB3: High level module block begin.  We don't have to do
      /* BB3: High level module block begin.  We don't have to do
         anything here.  The name is supposed to be the same as for
         anything here.  The name is supposed to be the same as for
         the BB1, but we don't check.  */
         the BB1, but we don't check.  */
      break;
      break;
 
 
    case 4:
    case 4:
      /* BB4: Global function.  */
      /* BB4: Global function.  */
      {
      {
        bfd_vma stackspace, typindx, offset;
        bfd_vma stackspace, typindx, offset;
        debug_type return_type;
        debug_type return_type;
 
 
        if (! ieee_read_number (info, pp, &stackspace)
        if (! ieee_read_number (info, pp, &stackspace)
            || ! ieee_read_number (info, pp, &typindx)
            || ! ieee_read_number (info, pp, &typindx)
            || ! ieee_read_expression (info, pp, &offset))
            || ! ieee_read_expression (info, pp, &offset))
          return FALSE;
          return FALSE;
 
 
        /* We have no way to record the stack space.  FIXME.  */
        /* We have no way to record the stack space.  FIXME.  */
 
 
        if (typindx < 256)
        if (typindx < 256)
          {
          {
            return_type = ieee_builtin_type (info, block_start, typindx);
            return_type = ieee_builtin_type (info, block_start, typindx);
            if (return_type == DEBUG_TYPE_NULL)
            if (return_type == DEBUG_TYPE_NULL)
              return FALSE;
              return FALSE;
          }
          }
        else
        else
          {
          {
            typindx -= 256;
            typindx -= 256;
            if (! ieee_alloc_type (info, typindx, TRUE))
            if (! ieee_alloc_type (info, typindx, TRUE))
              return FALSE;
              return FALSE;
            fnindx = typindx;
            fnindx = typindx;
            return_type = info->types.types[typindx].type;
            return_type = info->types.types[typindx].type;
            if (debug_get_type_kind (info->dhandle, return_type)
            if (debug_get_type_kind (info->dhandle, return_type)
                == DEBUG_KIND_FUNCTION)
                == DEBUG_KIND_FUNCTION)
              return_type = debug_get_return_type (info->dhandle,
              return_type = debug_get_return_type (info->dhandle,
                                                   return_type);
                                                   return_type);
          }
          }
 
 
        namcopy = savestring (name, namlen);
        namcopy = savestring (name, namlen);
        if (namcopy == NULL)
        if (namcopy == NULL)
          return FALSE;
          return FALSE;
        if (! debug_record_function (info->dhandle, namcopy, return_type,
        if (! debug_record_function (info->dhandle, namcopy, return_type,
                                     TRUE, offset))
                                     TRUE, offset))
          return FALSE;
          return FALSE;
      }
      }
      break;
      break;
 
 
    case 5:
    case 5:
      /* BB5: File name for source line numbers.  */
      /* BB5: File name for source line numbers.  */
      {
      {
        unsigned int i;
        unsigned int i;
 
 
        /* We ignore the date and time.  FIXME.  */
        /* We ignore the date and time.  FIXME.  */
        for (i = 0; i < 6; i++)
        for (i = 0; i < 6; i++)
          {
          {
            bfd_vma ignore;
            bfd_vma ignore;
            bfd_boolean present;
            bfd_boolean present;
 
 
            if (! ieee_read_optional_number (info, pp, &ignore, &present))
            if (! ieee_read_optional_number (info, pp, &ignore, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
          }
          }
 
 
        namcopy = savestring (name, namlen);
        namcopy = savestring (name, namlen);
        if (namcopy == NULL)
        if (namcopy == NULL)
          return FALSE;
          return FALSE;
        if (! debug_start_source (info->dhandle, namcopy))
        if (! debug_start_source (info->dhandle, namcopy))
          return FALSE;
          return FALSE;
      }
      }
      break;
      break;
 
 
    case 6:
    case 6:
      /* BB6: Local function or block.  */
      /* BB6: Local function or block.  */
      {
      {
        bfd_vma stackspace, typindx, offset;
        bfd_vma stackspace, typindx, offset;
 
 
        if (! ieee_read_number (info, pp, &stackspace)
        if (! ieee_read_number (info, pp, &stackspace)
            || ! ieee_read_number (info, pp, &typindx)
            || ! ieee_read_number (info, pp, &typindx)
            || ! ieee_read_expression (info, pp, &offset))
            || ! ieee_read_expression (info, pp, &offset))
          return FALSE;
          return FALSE;
 
 
        /* We have no way to record the stack space.  FIXME.  */
        /* We have no way to record the stack space.  FIXME.  */
 
 
        if (namlen == 0)
        if (namlen == 0)
          {
          {
            if (! debug_start_block (info->dhandle, offset))
            if (! debug_start_block (info->dhandle, offset))
              return FALSE;
              return FALSE;
            /* Change b to indicate that this is a block
            /* Change b to indicate that this is a block
               rather than a function.  */
               rather than a function.  */
            b = 0x86;
            b = 0x86;
          }
          }
        else
        else
          {
          {
            /* The MRI C++ compiler will output a fake function named
            /* The MRI C++ compiler will output a fake function named
               __XRYCPP to hold C++ debugging information.  We skip
               __XRYCPP to hold C++ debugging information.  We skip
               that function.  This is not crucial, but it makes
               that function.  This is not crucial, but it makes
               converting from IEEE to other debug formats work
               converting from IEEE to other debug formats work
               better.  */
               better.  */
            if (strncmp (name, "__XRYCPP", namlen) == 0)
            if (strncmp (name, "__XRYCPP", namlen) == 0)
              skip = TRUE;
              skip = TRUE;
            else
            else
              {
              {
                debug_type return_type;
                debug_type return_type;
 
 
                if (typindx < 256)
                if (typindx < 256)
                  {
                  {
                    return_type = ieee_builtin_type (info, block_start,
                    return_type = ieee_builtin_type (info, block_start,
                                                     typindx);
                                                     typindx);
                    if (return_type == NULL)
                    if (return_type == NULL)
                      return FALSE;
                      return FALSE;
                  }
                  }
                else
                else
                  {
                  {
                    typindx -= 256;
                    typindx -= 256;
                    if (! ieee_alloc_type (info, typindx, TRUE))
                    if (! ieee_alloc_type (info, typindx, TRUE))
                      return FALSE;
                      return FALSE;
                    fnindx = typindx;
                    fnindx = typindx;
                    return_type = info->types.types[typindx].type;
                    return_type = info->types.types[typindx].type;
                    if (debug_get_type_kind (info->dhandle, return_type)
                    if (debug_get_type_kind (info->dhandle, return_type)
                        == DEBUG_KIND_FUNCTION)
                        == DEBUG_KIND_FUNCTION)
                      return_type = debug_get_return_type (info->dhandle,
                      return_type = debug_get_return_type (info->dhandle,
                                                           return_type);
                                                           return_type);
                  }
                  }
 
 
                namcopy = savestring (name, namlen);
                namcopy = savestring (name, namlen);
                if (namcopy == NULL)
                if (namcopy == NULL)
                  return FALSE;
                  return FALSE;
                if (! debug_record_function (info->dhandle, namcopy,
                if (! debug_record_function (info->dhandle, namcopy,
                                             return_type, FALSE, offset))
                                             return_type, FALSE, offset))
                  return FALSE;
                  return FALSE;
              }
              }
          }
          }
      }
      }
      break;
      break;
 
 
    case 10:
    case 10:
      /* BB10: Assembler module scope.  In the normal case, we
      /* BB10: Assembler module scope.  In the normal case, we
         completely ignore all this information.  FIXME.  */
         completely ignore all this information.  FIXME.  */
      {
      {
        const char *inam, *vstr;
        const char *inam, *vstr;
        unsigned long inamlen, vstrlen;
        unsigned long inamlen, vstrlen;
        bfd_vma tool_type;
        bfd_vma tool_type;
        bfd_boolean present;
        bfd_boolean present;
        unsigned int i;
        unsigned int i;
 
 
        if (! info->saw_filename)
        if (! info->saw_filename)
          {
          {
            namcopy = savestring (name, namlen);
            namcopy = savestring (name, namlen);
            if (namcopy == NULL)
            if (namcopy == NULL)
              return FALSE;
              return FALSE;
            if (! debug_set_filename (info->dhandle, namcopy))
            if (! debug_set_filename (info->dhandle, namcopy))
              return FALSE;
              return FALSE;
            info->saw_filename = TRUE;
            info->saw_filename = TRUE;
          }
          }
 
 
        if (! ieee_read_id (info, pp, &inam, &inamlen)
        if (! ieee_read_id (info, pp, &inam, &inamlen)
            || ! ieee_read_number (info, pp, &tool_type)
            || ! ieee_read_number (info, pp, &tool_type)
            || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
            || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
          return FALSE;
          return FALSE;
        for (i = 0; i < 6; i++)
        for (i = 0; i < 6; i++)
          {
          {
            bfd_vma ignore;
            bfd_vma ignore;
 
 
            if (! ieee_read_optional_number (info, pp, &ignore, &present))
            if (! ieee_read_optional_number (info, pp, &ignore, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
          }
          }
      }
      }
      break;
      break;
 
 
    case 11:
    case 11:
      /* BB11: Module section.  We completely ignore all this
      /* BB11: Module section.  We completely ignore all this
         information.  FIXME.  */
         information.  FIXME.  */
      {
      {
        bfd_vma sectype, secindx, offset, map;
        bfd_vma sectype, secindx, offset, map;
        bfd_boolean present;
        bfd_boolean present;
 
 
        if (! ieee_read_number (info, pp, &sectype)
        if (! ieee_read_number (info, pp, &sectype)
            || ! ieee_read_number (info, pp, &secindx)
            || ! ieee_read_number (info, pp, &secindx)
            || ! ieee_read_expression (info, pp, &offset)
            || ! ieee_read_expression (info, pp, &offset)
            || ! ieee_read_optional_number (info, pp, &map, &present))
            || ! ieee_read_optional_number (info, pp, &map, &present))
          return FALSE;
          return FALSE;
      }
      }
      break;
      break;
 
 
    default:
    default:
      ieee_error (info, block_start, _("unknown BB type"));
      ieee_error (info, block_start, _("unknown BB type"));
      return FALSE;
      return FALSE;
    }
    }
 
 
 
 
  /* Push this block on the block stack.  */
  /* Push this block on the block stack.  */
 
 
  if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
  if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
    {
    {
      ieee_error (info, (const bfd_byte *) NULL, _("stack overflow"));
      ieee_error (info, (const bfd_byte *) NULL, _("stack overflow"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  info->blockstack.bsp->kind = b;
  info->blockstack.bsp->kind = b;
  if (b == 5)
  if (b == 5)
    info->blockstack.bsp->filename = namcopy;
    info->blockstack.bsp->filename = namcopy;
  info->blockstack.bsp->fnindx = fnindx;
  info->blockstack.bsp->fnindx = fnindx;
  info->blockstack.bsp->skip = skip;
  info->blockstack.bsp->skip = skip;
  ++info->blockstack.bsp;
  ++info->blockstack.bsp;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Handle an IEEE BE record.  */
/* Handle an IEEE BE record.  */
 
 
static bfd_boolean
static bfd_boolean
parse_ieee_be (struct ieee_info *info, const bfd_byte **pp)
parse_ieee_be (struct ieee_info *info, const bfd_byte **pp)
{
{
  bfd_vma offset;
  bfd_vma offset;
 
 
  if (info->blockstack.bsp <= info->blockstack.stack)
  if (info->blockstack.bsp <= info->blockstack.stack)
    {
    {
      ieee_error (info, *pp, _("stack underflow"));
      ieee_error (info, *pp, _("stack underflow"));
      return FALSE;
      return FALSE;
    }
    }
  --info->blockstack.bsp;
  --info->blockstack.bsp;
 
 
  switch (info->blockstack.bsp->kind)
  switch (info->blockstack.bsp->kind)
    {
    {
    case 2:
    case 2:
      /* When we end the global typedefs block, we copy out the
      /* When we end the global typedefs block, we copy out the
         contents of info->vars.  This is because the variable indices
         contents of info->vars.  This is because the variable indices
         may be reused in the local blocks.  However, we need to
         may be reused in the local blocks.  However, we need to
         preserve them so that we can locate a function returning a
         preserve them so that we can locate a function returning a
         reference variable whose type is named in the global typedef
         reference variable whose type is named in the global typedef
         block.  */
         block.  */
      info->global_vars = ((struct ieee_vars *)
      info->global_vars = ((struct ieee_vars *)
                           xmalloc (sizeof *info->global_vars));
                           xmalloc (sizeof *info->global_vars));
      info->global_vars->alloc = info->vars.alloc;
      info->global_vars->alloc = info->vars.alloc;
      info->global_vars->vars = ((struct ieee_var *)
      info->global_vars->vars = ((struct ieee_var *)
                                 xmalloc (info->vars.alloc
                                 xmalloc (info->vars.alloc
                                          * sizeof (*info->vars.vars)));
                                          * sizeof (*info->vars.vars)));
      memcpy (info->global_vars->vars, info->vars.vars,
      memcpy (info->global_vars->vars, info->vars.vars,
              info->vars.alloc * sizeof (*info->vars.vars));
              info->vars.alloc * sizeof (*info->vars.vars));
 
 
      /* We also copy out the non builtin parts of info->types, since
      /* We also copy out the non builtin parts of info->types, since
         the types are discarded when we start a new block.  */
         the types are discarded when we start a new block.  */
      info->global_types = ((struct ieee_types *)
      info->global_types = ((struct ieee_types *)
                            xmalloc (sizeof *info->global_types));
                            xmalloc (sizeof *info->global_types));
      info->global_types->alloc = info->types.alloc;
      info->global_types->alloc = info->types.alloc;
      info->global_types->types = ((struct ieee_type *)
      info->global_types->types = ((struct ieee_type *)
                                   xmalloc (info->types.alloc
                                   xmalloc (info->types.alloc
                                            * sizeof (*info->types.types)));
                                            * sizeof (*info->types.types)));
      memcpy (info->global_types->types, info->types.types,
      memcpy (info->global_types->types, info->types.types,
              info->types.alloc * sizeof (*info->types.types));
              info->types.alloc * sizeof (*info->types.types));
      memset (info->global_types->builtins, 0,
      memset (info->global_types->builtins, 0,
              sizeof (info->global_types->builtins));
              sizeof (info->global_types->builtins));
 
 
      break;
      break;
 
 
    case 4:
    case 4:
    case 6:
    case 6:
      if (! ieee_read_expression (info, pp, &offset))
      if (! ieee_read_expression (info, pp, &offset))
        return FALSE;
        return FALSE;
      if (! info->blockstack.bsp->skip)
      if (! info->blockstack.bsp->skip)
        {
        {
          if (! debug_end_function (info->dhandle, offset + 1))
          if (! debug_end_function (info->dhandle, offset + 1))
            return FALSE;
            return FALSE;
        }
        }
      break;
      break;
 
 
    case 0x86:
    case 0x86:
      /* This is BE6 when BB6 started a block rather than a local
      /* This is BE6 when BB6 started a block rather than a local
         function.  */
         function.  */
      if (! ieee_read_expression (info, pp, &offset))
      if (! ieee_read_expression (info, pp, &offset))
        return FALSE;
        return FALSE;
      if (! debug_end_block (info->dhandle, offset + 1))
      if (! debug_end_block (info->dhandle, offset + 1))
        return FALSE;
        return FALSE;
      break;
      break;
 
 
    case 5:
    case 5:
      /* When we end a BB5, we look up the stack for the last BB5, if
      /* When we end a BB5, we look up the stack for the last BB5, if
         there is one, so that we can call debug_start_source.  */
         there is one, so that we can call debug_start_source.  */
      if (info->blockstack.bsp > info->blockstack.stack)
      if (info->blockstack.bsp > info->blockstack.stack)
        {
        {
          struct ieee_block *bl;
          struct ieee_block *bl;
 
 
          bl = info->blockstack.bsp;
          bl = info->blockstack.bsp;
          do
          do
            {
            {
              --bl;
              --bl;
              if (bl->kind == 5)
              if (bl->kind == 5)
                {
                {
                  if (! debug_start_source (info->dhandle, bl->filename))
                  if (! debug_start_source (info->dhandle, bl->filename))
                    return FALSE;
                    return FALSE;
                  break;
                  break;
                }
                }
            }
            }
          while (bl != info->blockstack.stack);
          while (bl != info->blockstack.stack);
        }
        }
      break;
      break;
 
 
    case 11:
    case 11:
      if (! ieee_read_expression (info, pp, &offset))
      if (! ieee_read_expression (info, pp, &offset))
        return FALSE;
        return FALSE;
      /* We just ignore the module size.  FIXME.  */
      /* We just ignore the module size.  FIXME.  */
      break;
      break;
 
 
    default:
    default:
      /* Other block types do not have any trailing information.  */
      /* Other block types do not have any trailing information.  */
      break;
      break;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Parse an NN record.  */
/* Parse an NN record.  */
 
 
static bfd_boolean
static bfd_boolean
parse_ieee_nn (struct ieee_info *info, const bfd_byte **pp)
parse_ieee_nn (struct ieee_info *info, const bfd_byte **pp)
{
{
  const bfd_byte *nn_start;
  const bfd_byte *nn_start;
  bfd_vma varindx;
  bfd_vma varindx;
  const char *name;
  const char *name;
  unsigned long namlen;
  unsigned long namlen;
 
 
  nn_start = *pp;
  nn_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &varindx)
  if (! ieee_read_number (info, pp, &varindx)
      || ! ieee_read_id (info, pp, &name, &namlen))
      || ! ieee_read_id (info, pp, &name, &namlen))
    return FALSE;
    return FALSE;
 
 
  if (varindx < 32)
  if (varindx < 32)
    {
    {
      ieee_error (info, nn_start, _("illegal variable index"));
      ieee_error (info, nn_start, _("illegal variable index"));
      return FALSE;
      return FALSE;
    }
    }
  varindx -= 32;
  varindx -= 32;
 
 
  if (varindx >= info->vars.alloc)
  if (varindx >= info->vars.alloc)
    {
    {
      unsigned int alloc;
      unsigned int alloc;
 
 
      alloc = info->vars.alloc;
      alloc = info->vars.alloc;
      if (alloc == 0)
      if (alloc == 0)
        alloc = 4;
        alloc = 4;
      while (varindx >= alloc)
      while (varindx >= alloc)
        alloc *= 2;
        alloc *= 2;
      info->vars.vars = ((struct ieee_var *)
      info->vars.vars = ((struct ieee_var *)
                         xrealloc (info->vars.vars,
                         xrealloc (info->vars.vars,
                                   alloc * sizeof *info->vars.vars));
                                   alloc * sizeof *info->vars.vars));
      memset (info->vars.vars + info->vars.alloc, 0,
      memset (info->vars.vars + info->vars.alloc, 0,
              (alloc - info->vars.alloc) * sizeof *info->vars.vars);
              (alloc - info->vars.alloc) * sizeof *info->vars.vars);
      info->vars.alloc = alloc;
      info->vars.alloc = alloc;
    }
    }
 
 
  info->vars.vars[varindx].name = name;
  info->vars.vars[varindx].name = name;
  info->vars.vars[varindx].namlen = namlen;
  info->vars.vars[varindx].namlen = namlen;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Parse a TY record.  */
/* Parse a TY record.  */
 
 
static bfd_boolean
static bfd_boolean
parse_ieee_ty (struct ieee_info *info, const bfd_byte **pp)
parse_ieee_ty (struct ieee_info *info, const bfd_byte **pp)
{
{
  const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
  const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
  bfd_vma typeindx, varindx, tc;
  bfd_vma typeindx, varindx, tc;
  void *dhandle;
  void *dhandle;
  bfd_boolean tag, typdef;
  bfd_boolean tag, typdef;
  debug_type *arg_slots;
  debug_type *arg_slots;
  unsigned long type_bitsize;
  unsigned long type_bitsize;
  debug_type type;
  debug_type type;
 
 
  ty_start = *pp;
  ty_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &typeindx))
  if (! ieee_read_number (info, pp, &typeindx))
    return FALSE;
    return FALSE;
 
 
  if (typeindx < 256)
  if (typeindx < 256)
    {
    {
      ieee_error (info, ty_start, _("illegal type index"));
      ieee_error (info, ty_start, _("illegal type index"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  typeindx -= 256;
  typeindx -= 256;
  if (! ieee_alloc_type (info, typeindx, FALSE))
  if (! ieee_alloc_type (info, typeindx, FALSE))
    return FALSE;
    return FALSE;
 
 
  if (**pp != 0xce)
  if (**pp != 0xce)
    {
    {
      ieee_error (info, *pp, _("unknown TY code"));
      ieee_error (info, *pp, _("unknown TY code"));
      return FALSE;
      return FALSE;
    }
    }
  ++*pp;
  ++*pp;
 
 
  ty_var_start = *pp;
  ty_var_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &varindx))
  if (! ieee_read_number (info, pp, &varindx))
    return FALSE;
    return FALSE;
 
 
  if (varindx < 32)
  if (varindx < 32)
    {
    {
      ieee_error (info, ty_var_start, _("illegal variable index"));
      ieee_error (info, ty_var_start, _("illegal variable index"));
      return FALSE;
      return FALSE;
    }
    }
  varindx -= 32;
  varindx -= 32;
 
 
  if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
  if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
    {
    {
      ieee_error (info, ty_var_start, _("undefined variable in TY"));
      ieee_error (info, ty_var_start, _("undefined variable in TY"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  ty_code_start = *pp;
  ty_code_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &tc))
  if (! ieee_read_number (info, pp, &tc))
    return FALSE;
    return FALSE;
 
 
  dhandle = info->dhandle;
  dhandle = info->dhandle;
 
 
  tag = FALSE;
  tag = FALSE;
  typdef = FALSE;
  typdef = FALSE;
  arg_slots = NULL;
  arg_slots = NULL;
  type_bitsize = 0;
  type_bitsize = 0;
  switch (tc)
  switch (tc)
    {
    {
    default:
    default:
      ieee_error (info, ty_code_start, _("unknown TY code"));
      ieee_error (info, ty_code_start, _("unknown TY code"));
      return FALSE;
      return FALSE;
 
 
    case '!':
    case '!':
      /* Unknown type, with size.  We treat it as int.  FIXME.  */
      /* Unknown type, with size.  We treat it as int.  FIXME.  */
      {
      {
        bfd_vma size;
        bfd_vma size;
 
 
        if (! ieee_read_number (info, pp, &size))
        if (! ieee_read_number (info, pp, &size))
          return FALSE;
          return FALSE;
        type = debug_make_int_type (dhandle, size, FALSE);
        type = debug_make_int_type (dhandle, size, FALSE);
      }
      }
      break;
      break;
 
 
    case 'A': /* Array.  */
    case 'A': /* Array.  */
    case 'a': /* FORTRAN array in column/row order.  FIXME: Not
    case 'a': /* FORTRAN array in column/row order.  FIXME: Not
                 distinguished from normal array.  */
                 distinguished from normal array.  */
      {
      {
        debug_type ele_type;
        debug_type ele_type;
        bfd_vma lower, upper;
        bfd_vma lower, upper;
 
 
        if (! ieee_read_type_index (info, pp, &ele_type)
        if (! ieee_read_type_index (info, pp, &ele_type)
            || ! ieee_read_number (info, pp, &lower)
            || ! ieee_read_number (info, pp, &lower)
            || ! ieee_read_number (info, pp, &upper))
            || ! ieee_read_number (info, pp, &upper))
          return FALSE;
          return FALSE;
        type = debug_make_array_type (dhandle, ele_type,
        type = debug_make_array_type (dhandle, ele_type,
                                      ieee_builtin_type (info, ty_code_start,
                                      ieee_builtin_type (info, ty_code_start,
                                                         ((unsigned int)
                                                         ((unsigned int)
                                                          builtin_int)),
                                                          builtin_int)),
                                      (bfd_signed_vma) lower,
                                      (bfd_signed_vma) lower,
                                      (bfd_signed_vma) upper,
                                      (bfd_signed_vma) upper,
                                      FALSE);
                                      FALSE);
      }
      }
      break;
      break;
 
 
    case 'E':
    case 'E':
      /* Simple enumeration.  */
      /* Simple enumeration.  */
      {
      {
        bfd_vma size;
        bfd_vma size;
        unsigned int alloc;
        unsigned int alloc;
        const char **names;
        const char **names;
        unsigned int c;
        unsigned int c;
        bfd_signed_vma *vals;
        bfd_signed_vma *vals;
        unsigned int i;
        unsigned int i;
 
 
        if (! ieee_read_number (info, pp, &size))
        if (! ieee_read_number (info, pp, &size))
          return FALSE;
          return FALSE;
        /* FIXME: we ignore the enumeration size.  */
        /* FIXME: we ignore the enumeration size.  */
 
 
        alloc = 10;
        alloc = 10;
        names = (const char **) xmalloc (alloc * sizeof *names);
        names = (const char **) xmalloc (alloc * sizeof *names);
        memset (names, 0, alloc * sizeof *names);
        memset (names, 0, alloc * sizeof *names);
        c = 0;
        c = 0;
        while (1)
        while (1)
          {
          {
            const char *name;
            const char *name;
            unsigned long namlen;
            unsigned long namlen;
            bfd_boolean present;
            bfd_boolean present;
 
 
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
 
 
            if (c + 1 >= alloc)
            if (c + 1 >= alloc)
              {
              {
                alloc += 10;
                alloc += 10;
                names = ((const char **)
                names = ((const char **)
                         xrealloc (names, alloc * sizeof *names));
                         xrealloc (names, alloc * sizeof *names));
              }
              }
 
 
            names[c] = savestring (name, namlen);
            names[c] = savestring (name, namlen);
            if (names[c] == NULL)
            if (names[c] == NULL)
              return FALSE;
              return FALSE;
            ++c;
            ++c;
          }
          }
 
 
        names[c] = NULL;
        names[c] = NULL;
 
 
        vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
        vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
        for (i = 0; i < c; i++)
        for (i = 0; i < c; i++)
          vals[i] = i;
          vals[i] = i;
 
 
        type = debug_make_enum_type (dhandle, names, vals);
        type = debug_make_enum_type (dhandle, names, vals);
        tag = TRUE;
        tag = TRUE;
      }
      }
      break;
      break;
 
 
    case 'G':
    case 'G':
      /* Struct with bit fields.  */
      /* Struct with bit fields.  */
      {
      {
        bfd_vma size;
        bfd_vma size;
        unsigned int alloc;
        unsigned int alloc;
        debug_field *fields;
        debug_field *fields;
        unsigned int c;
        unsigned int c;
 
 
        if (! ieee_read_number (info, pp, &size))
        if (! ieee_read_number (info, pp, &size))
          return FALSE;
          return FALSE;
 
 
        alloc = 10;
        alloc = 10;
        fields = (debug_field *) xmalloc (alloc * sizeof *fields);
        fields = (debug_field *) xmalloc (alloc * sizeof *fields);
        c = 0;
        c = 0;
        while (1)
        while (1)
          {
          {
            const char *name;
            const char *name;
            unsigned long namlen;
            unsigned long namlen;
            bfd_boolean present;
            bfd_boolean present;
            debug_type ftype;
            debug_type ftype;
            bfd_vma bitpos, bitsize;
            bfd_vma bitpos, bitsize;
 
 
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
            if (! ieee_read_type_index (info, pp, &ftype)
            if (! ieee_read_type_index (info, pp, &ftype)
                || ! ieee_read_number (info, pp, &bitpos)
                || ! ieee_read_number (info, pp, &bitpos)
                || ! ieee_read_number (info, pp, &bitsize))
                || ! ieee_read_number (info, pp, &bitsize))
              return FALSE;
              return FALSE;
 
 
            if (c + 1 >= alloc)
            if (c + 1 >= alloc)
              {
              {
                alloc += 10;
                alloc += 10;
                fields = ((debug_field *)
                fields = ((debug_field *)
                          xrealloc (fields, alloc * sizeof *fields));
                          xrealloc (fields, alloc * sizeof *fields));
              }
              }
 
 
            fields[c] = debug_make_field (dhandle, savestring (name, namlen),
            fields[c] = debug_make_field (dhandle, savestring (name, namlen),
                                          ftype, bitpos, bitsize,
                                          ftype, bitpos, bitsize,
                                          DEBUG_VISIBILITY_PUBLIC);
                                          DEBUG_VISIBILITY_PUBLIC);
            if (fields[c] == NULL)
            if (fields[c] == NULL)
              return FALSE;
              return FALSE;
            ++c;
            ++c;
          }
          }
 
 
        fields[c] = NULL;
        fields[c] = NULL;
 
 
        type = debug_make_struct_type (dhandle, TRUE, size, fields);
        type = debug_make_struct_type (dhandle, TRUE, size, fields);
        tag = TRUE;
        tag = TRUE;
      }
      }
      break;
      break;
 
 
    case 'N':
    case 'N':
      /* Enumeration.  */
      /* Enumeration.  */
      {
      {
        unsigned int alloc;
        unsigned int alloc;
        const char **names;
        const char **names;
        bfd_signed_vma *vals;
        bfd_signed_vma *vals;
        unsigned int c;
        unsigned int c;
 
 
        alloc = 10;
        alloc = 10;
        names = (const char **) xmalloc (alloc * sizeof *names);
        names = (const char **) xmalloc (alloc * sizeof *names);
        vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
        vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
        c = 0;
        c = 0;
        while (1)
        while (1)
          {
          {
            const char *name;
            const char *name;
            unsigned long namlen;
            unsigned long namlen;
            bfd_boolean present;
            bfd_boolean present;
            bfd_vma val;
            bfd_vma val;
 
 
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
            if (! ieee_read_number (info, pp, &val))
            if (! ieee_read_number (info, pp, &val))
              return FALSE;
              return FALSE;
 
 
            /* If the length of the name is zero, then the value is
            /* If the length of the name is zero, then the value is
               actually the size of the enum.  We ignore this
               actually the size of the enum.  We ignore this
               information.  FIXME.  */
               information.  FIXME.  */
            if (namlen == 0)
            if (namlen == 0)
              continue;
              continue;
 
 
            if (c + 1 >= alloc)
            if (c + 1 >= alloc)
              {
              {
                alloc += 10;
                alloc += 10;
                names = ((const char **)
                names = ((const char **)
                         xrealloc (names, alloc * sizeof *names));
                         xrealloc (names, alloc * sizeof *names));
                vals = ((bfd_signed_vma *)
                vals = ((bfd_signed_vma *)
                        xrealloc (vals, alloc * sizeof *vals));
                        xrealloc (vals, alloc * sizeof *vals));
              }
              }
 
 
            names[c] = savestring (name, namlen);
            names[c] = savestring (name, namlen);
            if (names[c] == NULL)
            if (names[c] == NULL)
              return FALSE;
              return FALSE;
            vals[c] = (bfd_signed_vma) val;
            vals[c] = (bfd_signed_vma) val;
            ++c;
            ++c;
          }
          }
 
 
        names[c] = NULL;
        names[c] = NULL;
 
 
        type = debug_make_enum_type (dhandle, names, vals);
        type = debug_make_enum_type (dhandle, names, vals);
        tag = TRUE;
        tag = TRUE;
      }
      }
      break;
      break;
 
 
    case 'O': /* Small pointer.  We don't distinguish small and large
    case 'O': /* Small pointer.  We don't distinguish small and large
                 pointers.  FIXME.  */
                 pointers.  FIXME.  */
    case 'P': /* Large pointer.  */
    case 'P': /* Large pointer.  */
      {
      {
        debug_type t;
        debug_type t;
 
 
        if (! ieee_read_type_index (info, pp, &t))
        if (! ieee_read_type_index (info, pp, &t))
          return FALSE;
          return FALSE;
        type = debug_make_pointer_type (dhandle, t);
        type = debug_make_pointer_type (dhandle, t);
      }
      }
      break;
      break;
 
 
    case 'R':
    case 'R':
      /* Range.  */
      /* Range.  */
      {
      {
        bfd_vma low, high, signedp, size;
        bfd_vma low, high, signedp, size;
 
 
        if (! ieee_read_number (info, pp, &low)
        if (! ieee_read_number (info, pp, &low)
            || ! ieee_read_number (info, pp, &high)
            || ! ieee_read_number (info, pp, &high)
            || ! ieee_read_number (info, pp, &signedp)
            || ! ieee_read_number (info, pp, &signedp)
            || ! ieee_read_number (info, pp, &size))
            || ! ieee_read_number (info, pp, &size))
          return FALSE;
          return FALSE;
 
 
        type = debug_make_range_type (dhandle,
        type = debug_make_range_type (dhandle,
                                      debug_make_int_type (dhandle, size,
                                      debug_make_int_type (dhandle, size,
                                                           ! signedp),
                                                           ! signedp),
                                      (bfd_signed_vma) low,
                                      (bfd_signed_vma) low,
                                      (bfd_signed_vma) high);
                                      (bfd_signed_vma) high);
      }
      }
      break;
      break;
 
 
    case 'S': /* Struct.  */
    case 'S': /* Struct.  */
    case 'U': /* Union.  */
    case 'U': /* Union.  */
      {
      {
        bfd_vma size;
        bfd_vma size;
        unsigned int alloc;
        unsigned int alloc;
        debug_field *fields;
        debug_field *fields;
        unsigned int c;
        unsigned int c;
 
 
        if (! ieee_read_number (info, pp, &size))
        if (! ieee_read_number (info, pp, &size))
          return FALSE;
          return FALSE;
 
 
        alloc = 10;
        alloc = 10;
        fields = (debug_field *) xmalloc (alloc * sizeof *fields);
        fields = (debug_field *) xmalloc (alloc * sizeof *fields);
        c = 0;
        c = 0;
        while (1)
        while (1)
          {
          {
            const char *name;
            const char *name;
            unsigned long namlen;
            unsigned long namlen;
            bfd_boolean present;
            bfd_boolean present;
            bfd_vma tindx;
            bfd_vma tindx;
            bfd_vma offset;
            bfd_vma offset;
            debug_type ftype;
            debug_type ftype;
            bfd_vma bitsize;
            bfd_vma bitsize;
 
 
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              return FALSE;
              return FALSE;
            if (! present)
            if (! present)
              break;
              break;
            if (! ieee_read_number (info, pp, &tindx)
            if (! ieee_read_number (info, pp, &tindx)
                || ! ieee_read_number (info, pp, &offset))
                || ! ieee_read_number (info, pp, &offset))
              return FALSE;
              return FALSE;
 
 
            if (tindx < 256)
            if (tindx < 256)
              {
              {
                ftype = ieee_builtin_type (info, ty_code_start, tindx);
                ftype = ieee_builtin_type (info, ty_code_start, tindx);
                bitsize = 0;
                bitsize = 0;
                offset *= 8;
                offset *= 8;
              }
              }
            else
            else
              {
              {
                struct ieee_type *t;
                struct ieee_type *t;
 
 
                tindx -= 256;
                tindx -= 256;
                if (! ieee_alloc_type (info, tindx, TRUE))
                if (! ieee_alloc_type (info, tindx, TRUE))
                  return FALSE;
                  return FALSE;
                t = info->types.types + tindx;
                t = info->types.types + tindx;
                ftype = t->type;
                ftype = t->type;
                bitsize = t->bitsize;
                bitsize = t->bitsize;
                if (bitsize == 0)
                if (bitsize == 0)
                  offset *= 8;
                  offset *= 8;
              }
              }
 
 
            if (c + 1 >= alloc)
            if (c + 1 >= alloc)
              {
              {
                alloc += 10;
                alloc += 10;
                fields = ((debug_field *)
                fields = ((debug_field *)
                          xrealloc (fields, alloc * sizeof *fields));
                          xrealloc (fields, alloc * sizeof *fields));
              }
              }
 
 
            fields[c] = debug_make_field (dhandle, savestring (name, namlen),
            fields[c] = debug_make_field (dhandle, savestring (name, namlen),
                                          ftype, offset, bitsize,
                                          ftype, offset, bitsize,
                                          DEBUG_VISIBILITY_PUBLIC);
                                          DEBUG_VISIBILITY_PUBLIC);
            if (fields[c] == NULL)
            if (fields[c] == NULL)
              return FALSE;
              return FALSE;
            ++c;
            ++c;
          }
          }
 
 
        fields[c] = NULL;
        fields[c] = NULL;
 
 
        type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
        type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
        tag = TRUE;
        tag = TRUE;
      }
      }
      break;
      break;
 
 
    case 'T':
    case 'T':
      /* Typedef.  */
      /* Typedef.  */
      if (! ieee_read_type_index (info, pp, &type))
      if (! ieee_read_type_index (info, pp, &type))
        return FALSE;
        return FALSE;
      typdef = TRUE;
      typdef = TRUE;
      break;
      break;
 
 
    case 'X':
    case 'X':
      /* Procedure.  FIXME: This is an extern declaration, which we
      /* Procedure.  FIXME: This is an extern declaration, which we
         have no way of representing.  */
         have no way of representing.  */
      {
      {
        bfd_vma attr;
        bfd_vma attr;
        debug_type rtype;
        debug_type rtype;
        bfd_vma nargs;
        bfd_vma nargs;
        bfd_boolean present;
        bfd_boolean present;
        struct ieee_var *pv;
        struct ieee_var *pv;
 
 
        /* FIXME: We ignore the attribute and the argument names.  */
        /* FIXME: We ignore the attribute and the argument names.  */
 
 
        if (! ieee_read_number (info, pp, &attr)
        if (! ieee_read_number (info, pp, &attr)
            || ! ieee_read_type_index (info, pp, &rtype)
            || ! ieee_read_type_index (info, pp, &rtype)
            || ! ieee_read_number (info, pp, &nargs))
            || ! ieee_read_number (info, pp, &nargs))
          return FALSE;
          return FALSE;
        do
        do
          {
          {
            const char *name;
            const char *name;
            unsigned long namlen;
            unsigned long namlen;
 
 
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
            if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              return FALSE;
              return FALSE;
          }
          }
        while (present);
        while (present);
 
 
        pv = info->vars.vars + varindx;
        pv = info->vars.vars + varindx;
        pv->kind = IEEE_EXTERNAL;
        pv->kind = IEEE_EXTERNAL;
        if (pv->namlen > 0
        if (pv->namlen > 0
            && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
            && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
          {
          {
            /* Set up the return type as an indirect type pointing to
            /* Set up the return type as an indirect type pointing to
               the variable slot, so that we can change it to a
               the variable slot, so that we can change it to a
               reference later if appropriate.  */
               reference later if appropriate.  */
            pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
            pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
            *pv->pslot = rtype;
            *pv->pslot = rtype;
            rtype = debug_make_indirect_type (dhandle, pv->pslot,
            rtype = debug_make_indirect_type (dhandle, pv->pslot,
                                              (const char *) NULL);
                                              (const char *) NULL);
          }
          }
 
 
        type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
        type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
                                         FALSE);
                                         FALSE);
      }
      }
      break;
      break;
 
 
    case 'V':
    case 'V':
      /* Void.  This is not documented, but the MRI compiler emits it.  */
      /* Void.  This is not documented, but the MRI compiler emits it.  */
      type = debug_make_void_type (dhandle);
      type = debug_make_void_type (dhandle);
      break;
      break;
 
 
    case 'Z':
    case 'Z':
      /* Array with 0 lower bound.  */
      /* Array with 0 lower bound.  */
      {
      {
        debug_type etype;
        debug_type etype;
        bfd_vma high;
        bfd_vma high;
 
 
        if (! ieee_read_type_index (info, pp, &etype)
        if (! ieee_read_type_index (info, pp, &etype)
            || ! ieee_read_number (info, pp, &high))
            || ! ieee_read_number (info, pp, &high))
          return FALSE;
          return FALSE;
 
 
        type = debug_make_array_type (dhandle, etype,
        type = debug_make_array_type (dhandle, etype,
                                      ieee_builtin_type (info, ty_code_start,
                                      ieee_builtin_type (info, ty_code_start,
                                                         ((unsigned int)
                                                         ((unsigned int)
                                                          builtin_int)),
                                                          builtin_int)),
                                      0, (bfd_signed_vma) high, FALSE);
                                      0, (bfd_signed_vma) high, FALSE);
      }
      }
      break;
      break;
 
 
    case 'c': /* Complex.  */
    case 'c': /* Complex.  */
    case 'd': /* Double complex.  */
    case 'd': /* Double complex.  */
      {
      {
        const char *name;
        const char *name;
        unsigned long namlen;
        unsigned long namlen;
 
 
        /* FIXME: I don't know what the name means.  */
        /* FIXME: I don't know what the name means.  */
 
 
        if (! ieee_read_id (info, pp, &name, &namlen))
        if (! ieee_read_id (info, pp, &name, &namlen))
          return FALSE;
          return FALSE;
 
 
        type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
        type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
      }
      }
      break;
      break;
 
 
    case 'f':
    case 'f':
      /* Pascal file name.  FIXME.  */
      /* Pascal file name.  FIXME.  */
      ieee_error (info, ty_code_start, _("Pascal file name not supported"));
      ieee_error (info, ty_code_start, _("Pascal file name not supported"));
      return FALSE;
      return FALSE;
 
 
    case 'g':
    case 'g':
      /* Bitfield type.  */
      /* Bitfield type.  */
      {
      {
        bfd_vma signedp, bitsize, dummy;
        bfd_vma signedp, bitsize, dummy;
        const bfd_byte *hold;
        const bfd_byte *hold;
        bfd_boolean present;
        bfd_boolean present;
 
 
        if (! ieee_read_number (info, pp, &signedp)
        if (! ieee_read_number (info, pp, &signedp)
            || ! ieee_read_number (info, pp, &bitsize))
            || ! ieee_read_number (info, pp, &bitsize))
          return FALSE;
          return FALSE;
 
 
        /* I think the documentation says that there is a type index,
        /* I think the documentation says that there is a type index,
           but some actual files do not have one.  */
           but some actual files do not have one.  */
        hold = *pp;
        hold = *pp;
        if (! ieee_read_optional_number (info, pp, &dummy, &present))
        if (! ieee_read_optional_number (info, pp, &dummy, &present))
          return FALSE;
          return FALSE;
        if (! present)
        if (! present)
          {
          {
            /* FIXME: This is just a guess.  */
            /* FIXME: This is just a guess.  */
            type = debug_make_int_type (dhandle, 4,
            type = debug_make_int_type (dhandle, 4,
                                        signedp ? FALSE : TRUE);
                                        signedp ? FALSE : TRUE);
          }
          }
        else
        else
          {
          {
            *pp = hold;
            *pp = hold;
            if (! ieee_read_type_index (info, pp, &type))
            if (! ieee_read_type_index (info, pp, &type))
              return FALSE;
              return FALSE;
          }
          }
        type_bitsize = bitsize;
        type_bitsize = bitsize;
      }
      }
      break;
      break;
 
 
    case 'n':
    case 'n':
      /* Qualifier.  */
      /* Qualifier.  */
      {
      {
        bfd_vma kind;
        bfd_vma kind;
        debug_type t;
        debug_type t;
 
 
        if (! ieee_read_number (info, pp, &kind)
        if (! ieee_read_number (info, pp, &kind)
            || ! ieee_read_type_index (info, pp, &t))
            || ! ieee_read_type_index (info, pp, &t))
          return FALSE;
          return FALSE;
 
 
        switch (kind)
        switch (kind)
          {
          {
          default:
          default:
            ieee_error (info, ty_start, _("unsupported qualifier"));
            ieee_error (info, ty_start, _("unsupported qualifier"));
            return FALSE;
            return FALSE;
 
 
          case 1:
          case 1:
            type = debug_make_const_type (dhandle, t);
            type = debug_make_const_type (dhandle, t);
            break;
            break;
 
 
          case 2:
          case 2:
            type = debug_make_volatile_type (dhandle, t);
            type = debug_make_volatile_type (dhandle, t);
            break;
            break;
          }
          }
      }
      }
      break;
      break;
 
 
    case 's':
    case 's':
      /* Set.  */
      /* Set.  */
      {
      {
        bfd_vma size;
        bfd_vma size;
        debug_type etype;
        debug_type etype;
 
 
        if (! ieee_read_number (info, pp, &size)
        if (! ieee_read_number (info, pp, &size)
            || ! ieee_read_type_index (info, pp, &etype))
            || ! ieee_read_type_index (info, pp, &etype))
          return FALSE;
          return FALSE;
 
 
        /* FIXME: We ignore the size.  */
        /* FIXME: We ignore the size.  */
 
 
        type = debug_make_set_type (dhandle, etype, FALSE);
        type = debug_make_set_type (dhandle, etype, FALSE);
      }
      }
      break;
      break;
 
 
    case 'x':
    case 'x':
      /* Procedure with compiler dependencies.  */
      /* Procedure with compiler dependencies.  */
      {
      {
        struct ieee_var *pv;
        struct ieee_var *pv;
        bfd_vma attr, frame_type, push_mask, nargs, level, father;
        bfd_vma attr, frame_type, push_mask, nargs, level, father;
        debug_type rtype;
        debug_type rtype;
        debug_type *arg_types;
        debug_type *arg_types;
        bfd_boolean varargs;
        bfd_boolean varargs;
        bfd_boolean present;
        bfd_boolean present;
 
 
        /* FIXME: We ignore some of this information.  */
        /* FIXME: We ignore some of this information.  */
 
 
        pv = info->vars.vars + varindx;
        pv = info->vars.vars + varindx;
 
 
        if (! ieee_read_number (info, pp, &attr)
        if (! ieee_read_number (info, pp, &attr)
            || ! ieee_read_number (info, pp, &frame_type)
            || ! ieee_read_number (info, pp, &frame_type)
            || ! ieee_read_number (info, pp, &push_mask)
            || ! ieee_read_number (info, pp, &push_mask)
            || ! ieee_read_type_index (info, pp, &rtype)
            || ! ieee_read_type_index (info, pp, &rtype)
            || ! ieee_read_number (info, pp, &nargs))
            || ! ieee_read_number (info, pp, &nargs))
          return FALSE;
          return FALSE;
        if (nargs == (bfd_vma) -1)
        if (nargs == (bfd_vma) -1)
          {
          {
            arg_types = NULL;
            arg_types = NULL;
            varargs = FALSE;
            varargs = FALSE;
          }
          }
        else
        else
          {
          {
            unsigned int i;
            unsigned int i;
 
 
            arg_types = ((debug_type *)
            arg_types = ((debug_type *)
                         xmalloc ((nargs + 1) * sizeof *arg_types));
                         xmalloc ((nargs + 1) * sizeof *arg_types));
            for (i = 0; i < nargs; i++)
            for (i = 0; i < nargs; i++)
              if (! ieee_read_type_index (info, pp, arg_types + i))
              if (! ieee_read_type_index (info, pp, arg_types + i))
                return FALSE;
                return FALSE;
 
 
            /* If the last type is pointer to void, this is really a
            /* If the last type is pointer to void, this is really a
               varargs function.  */
               varargs function.  */
            varargs = FALSE;
            varargs = FALSE;
            if (nargs > 0)
            if (nargs > 0)
              {
              {
                debug_type last;
                debug_type last;
 
 
                last = arg_types[nargs - 1];
                last = arg_types[nargs - 1];
                if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
                if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
                    && (debug_get_type_kind (dhandle,
                    && (debug_get_type_kind (dhandle,
                                             debug_get_target_type (dhandle,
                                             debug_get_target_type (dhandle,
                                                                    last))
                                                                    last))
                        == DEBUG_KIND_VOID))
                        == DEBUG_KIND_VOID))
                  {
                  {
                    --nargs;
                    --nargs;
                    varargs = TRUE;
                    varargs = TRUE;
                  }
                  }
              }
              }
 
 
            /* If there are any pointer arguments, turn them into
            /* If there are any pointer arguments, turn them into
               indirect types in case we later need to convert them to
               indirect types in case we later need to convert them to
               reference types.  */
               reference types.  */
            for (i = 0; i < nargs; i++)
            for (i = 0; i < nargs; i++)
              {
              {
                if (debug_get_type_kind (dhandle, arg_types[i])
                if (debug_get_type_kind (dhandle, arg_types[i])
                    == DEBUG_KIND_POINTER)
                    == DEBUG_KIND_POINTER)
                  {
                  {
                    if (arg_slots == NULL)
                    if (arg_slots == NULL)
                      {
                      {
                        arg_slots = ((debug_type *)
                        arg_slots = ((debug_type *)
                                     xmalloc (nargs * sizeof *arg_slots));
                                     xmalloc (nargs * sizeof *arg_slots));
                        memset (arg_slots, 0, nargs * sizeof *arg_slots);
                        memset (arg_slots, 0, nargs * sizeof *arg_slots);
                      }
                      }
                    arg_slots[i] = arg_types[i];
                    arg_slots[i] = arg_types[i];
                    arg_types[i] =
                    arg_types[i] =
                      debug_make_indirect_type (dhandle,
                      debug_make_indirect_type (dhandle,
                                                arg_slots + i,
                                                arg_slots + i,
                                                (const char *) NULL);
                                                (const char *) NULL);
                  }
                  }
              }
              }
 
 
            arg_types[nargs] = DEBUG_TYPE_NULL;
            arg_types[nargs] = DEBUG_TYPE_NULL;
          }
          }
        if (! ieee_read_number (info, pp, &level)
        if (! ieee_read_number (info, pp, &level)
            || ! ieee_read_optional_number (info, pp, &father, &present))
            || ! ieee_read_optional_number (info, pp, &father, &present))
          return FALSE;
          return FALSE;
 
 
        /* We can't distinguish between a global function and a static
        /* We can't distinguish between a global function and a static
           function.  */
           function.  */
        pv->kind = IEEE_FUNCTION;
        pv->kind = IEEE_FUNCTION;
 
 
        if (pv->namlen > 0
        if (pv->namlen > 0
            && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
            && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
          {
          {
            /* Set up the return type as an indirect type pointing to
            /* Set up the return type as an indirect type pointing to
               the variable slot, so that we can change it to a
               the variable slot, so that we can change it to a
               reference later if appropriate.  */
               reference later if appropriate.  */
            pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
            pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
            *pv->pslot = rtype;
            *pv->pslot = rtype;
            rtype = debug_make_indirect_type (dhandle, pv->pslot,
            rtype = debug_make_indirect_type (dhandle, pv->pslot,
                                              (const char *) NULL);
                                              (const char *) NULL);
          }
          }
 
 
        type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
        type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
      }
      }
      break;
      break;
    }
    }
 
 
  /* Record the type in the table.  */
  /* Record the type in the table.  */
 
 
  if (type == DEBUG_TYPE_NULL)
  if (type == DEBUG_TYPE_NULL)
    return FALSE;
    return FALSE;
 
 
  info->vars.vars[varindx].type = type;
  info->vars.vars[varindx].type = type;
 
 
  if ((tag || typdef)
  if ((tag || typdef)
      && info->vars.vars[varindx].namlen > 0)
      && info->vars.vars[varindx].namlen > 0)
    {
    {
      const char *name;
      const char *name;
 
 
      name = savestring (info->vars.vars[varindx].name,
      name = savestring (info->vars.vars[varindx].name,
                         info->vars.vars[varindx].namlen);
                         info->vars.vars[varindx].namlen);
      if (typdef)
      if (typdef)
        type = debug_name_type (dhandle, name, type);
        type = debug_name_type (dhandle, name, type);
      else if (tc == 'E' || tc == 'N')
      else if (tc == 'E' || tc == 'N')
        type = debug_tag_type (dhandle, name, type);
        type = debug_tag_type (dhandle, name, type);
      else
      else
        {
        {
          struct ieee_tag *it;
          struct ieee_tag *it;
 
 
          /* We must allocate all struct tags as indirect types, so
          /* We must allocate all struct tags as indirect types, so
             that if we later see a definition of the tag as a C++
             that if we later see a definition of the tag as a C++
             record we can update the indirect slot and automatically
             record we can update the indirect slot and automatically
             change all the existing references.  */
             change all the existing references.  */
          it = (struct ieee_tag *) xmalloc (sizeof *it);
          it = (struct ieee_tag *) xmalloc (sizeof *it);
          memset (it, 0, sizeof *it);
          memset (it, 0, sizeof *it);
          it->next = info->tags;
          it->next = info->tags;
          info->tags = it;
          info->tags = it;
          it->name = name;
          it->name = name;
          it->slot = type;
          it->slot = type;
 
 
          type = debug_make_indirect_type (dhandle, &it->slot, name);
          type = debug_make_indirect_type (dhandle, &it->slot, name);
          type = debug_tag_type (dhandle, name, type);
          type = debug_tag_type (dhandle, name, type);
 
 
          it->type = type;
          it->type = type;
        }
        }
      if (type == NULL)
      if (type == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  info->types.types[typeindx].type = type;
  info->types.types[typeindx].type = type;
  info->types.types[typeindx].arg_slots = arg_slots;
  info->types.types[typeindx].arg_slots = arg_slots;
  info->types.types[typeindx].bitsize = type_bitsize;
  info->types.types[typeindx].bitsize = type_bitsize;
 
 
  /* We may have already allocated type as an indirect type pointing
  /* We may have already allocated type as an indirect type pointing
     to slot.  It does no harm to replace the indirect type with the
     to slot.  It does no harm to replace the indirect type with the
     real type.  Filling in slot as well handles the indirect types
     real type.  Filling in slot as well handles the indirect types
     which are already hanging around.  */
     which are already hanging around.  */
  if (info->types.types[typeindx].pslot != NULL)
  if (info->types.types[typeindx].pslot != NULL)
    *info->types.types[typeindx].pslot = type;
    *info->types.types[typeindx].pslot = type;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Parse an ATN record.  */
/* Parse an ATN record.  */
 
 
static bfd_boolean
static bfd_boolean
parse_ieee_atn (struct ieee_info *info, const bfd_byte **pp)
parse_ieee_atn (struct ieee_info *info, const bfd_byte **pp)
{
{
  const bfd_byte *atn_start, *atn_code_start;
  const bfd_byte *atn_start, *atn_code_start;
  bfd_vma varindx;
  bfd_vma varindx;
  struct ieee_var *pvar;
  struct ieee_var *pvar;
  debug_type type;
  debug_type type;
  bfd_vma atn_code;
  bfd_vma atn_code;
  void *dhandle;
  void *dhandle;
  bfd_vma v, v2, v3, v4, v5;
  bfd_vma v, v2, v3, v4, v5;
  const char *name;
  const char *name;
  unsigned long namlen;
  unsigned long namlen;
  char *namcopy;
  char *namcopy;
  bfd_boolean present;
  bfd_boolean present;
  int blocktype;
  int blocktype;
 
 
  atn_start = *pp;
  atn_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &varindx)
  if (! ieee_read_number (info, pp, &varindx)
      || ! ieee_read_type_index (info, pp, &type))
      || ! ieee_read_type_index (info, pp, &type))
    return FALSE;
    return FALSE;
 
 
  atn_code_start = *pp;
  atn_code_start = *pp;
 
 
  if (! ieee_read_number (info, pp, &atn_code))
  if (! ieee_read_number (info, pp, &atn_code))
    return FALSE;
    return FALSE;
 
 
  if (varindx == 0)
  if (varindx == 0)
    {
    {
      pvar = NULL;
      pvar = NULL;
      name = "";
      name = "";
      namlen = 0;
      namlen = 0;
    }
    }
  else if (varindx < 32)
  else if (varindx < 32)
    {
    {
      /* The MRI compiler reportedly sometimes emits variable lifetime
      /* The MRI compiler reportedly sometimes emits variable lifetime
         information for a register.  We just ignore it.  */
         information for a register.  We just ignore it.  */
      if (atn_code == 9)
      if (atn_code == 9)
        return ieee_read_number (info, pp, &v);
        return ieee_read_number (info, pp, &v);
 
 
      ieee_error (info, atn_start, _("illegal variable index"));
      ieee_error (info, atn_start, _("illegal variable index"));
      return FALSE;
      return FALSE;
    }
    }
  else
  else
    {
    {
      varindx -= 32;
      varindx -= 32;
      if (varindx >= info->vars.alloc
      if (varindx >= info->vars.alloc
          || info->vars.vars[varindx].name == NULL)
          || info->vars.vars[varindx].name == NULL)
        {
        {
          /* The MRI compiler or linker sometimes omits the NN record
          /* The MRI compiler or linker sometimes omits the NN record
             for a pmisc record.  */
             for a pmisc record.  */
          if (atn_code == 62)
          if (atn_code == 62)
            {
            {
              if (varindx >= info->vars.alloc)
              if (varindx >= info->vars.alloc)
                {
                {
                  unsigned int alloc;
                  unsigned int alloc;
 
 
                  alloc = info->vars.alloc;
                  alloc = info->vars.alloc;
                  if (alloc == 0)
                  if (alloc == 0)
                    alloc = 4;
                    alloc = 4;
                  while (varindx >= alloc)
                  while (varindx >= alloc)
                    alloc *= 2;
                    alloc *= 2;
                  info->vars.vars = ((struct ieee_var *)
                  info->vars.vars = ((struct ieee_var *)
                                     xrealloc (info->vars.vars,
                                     xrealloc (info->vars.vars,
                                               (alloc
                                               (alloc
                                                * sizeof *info->vars.vars)));
                                                * sizeof *info->vars.vars)));
                  memset (info->vars.vars + info->vars.alloc, 0,
                  memset (info->vars.vars + info->vars.alloc, 0,
                          ((alloc - info->vars.alloc)
                          ((alloc - info->vars.alloc)
                           * sizeof *info->vars.vars));
                           * sizeof *info->vars.vars));
                  info->vars.alloc = alloc;
                  info->vars.alloc = alloc;
                }
                }
 
 
              pvar = info->vars.vars + varindx;
              pvar = info->vars.vars + varindx;
              pvar->name = "";
              pvar->name = "";
              pvar->namlen = 0;
              pvar->namlen = 0;
            }
            }
          else
          else
            {
            {
              ieee_error (info, atn_start, _("undefined variable in ATN"));
              ieee_error (info, atn_start, _("undefined variable in ATN"));
              return FALSE;
              return FALSE;
            }
            }
        }
        }
 
 
      pvar = info->vars.vars + varindx;
      pvar = info->vars.vars + varindx;
 
 
      pvar->type = type;
      pvar->type = type;
 
 
      name = pvar->name;
      name = pvar->name;
      namlen = pvar->namlen;
      namlen = pvar->namlen;
    }
    }
 
 
  dhandle = info->dhandle;
  dhandle = info->dhandle;
 
 
  /* If we are going to call debug_record_variable with a pointer
  /* If we are going to call debug_record_variable with a pointer
     type, change the type to an indirect type so that we can later
     type, change the type to an indirect type so that we can later
     change it to a reference type if we encounter a C++ pmisc 'R'
     change it to a reference type if we encounter a C++ pmisc 'R'
     record.  */
     record.  */
  if (pvar != NULL
  if (pvar != NULL
      && type != DEBUG_TYPE_NULL
      && type != DEBUG_TYPE_NULL
      && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
      && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
    {
    {
      switch (atn_code)
      switch (atn_code)
        {
        {
        case 1:
        case 1:
        case 2:
        case 2:
        case 3:
        case 3:
        case 5:
        case 5:
        case 8:
        case 8:
        case 10:
        case 10:
          pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
          pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
          *pvar->pslot = type;
          *pvar->pslot = type;
          type = debug_make_indirect_type (dhandle, pvar->pslot,
          type = debug_make_indirect_type (dhandle, pvar->pslot,
                                           (const char *) NULL);
                                           (const char *) NULL);
          pvar->type = type;
          pvar->type = type;
          break;
          break;
        }
        }
    }
    }
 
 
  switch (atn_code)
  switch (atn_code)
    {
    {
    default:
    default:
      ieee_error (info, atn_code_start, _("unknown ATN type"));
      ieee_error (info, atn_code_start, _("unknown ATN type"));
      return FALSE;
      return FALSE;
 
 
    case 1:
    case 1:
      /* Automatic variable.  */
      /* Automatic variable.  */
      if (! ieee_read_number (info, pp, &v))
      if (! ieee_read_number (info, pp, &v))
        return FALSE;
        return FALSE;
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (type == NULL)
      if (type == NULL)
        type = debug_make_void_type (dhandle);
        type = debug_make_void_type (dhandle);
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_LOCAL;
        pvar->kind = IEEE_LOCAL;
      return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
      return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
 
 
    case 2:
    case 2:
      /* Register variable.  */
      /* Register variable.  */
      if (! ieee_read_number (info, pp, &v))
      if (! ieee_read_number (info, pp, &v))
        return FALSE;
        return FALSE;
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (type == NULL)
      if (type == NULL)
        type = debug_make_void_type (dhandle);
        type = debug_make_void_type (dhandle);
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_LOCAL;
        pvar->kind = IEEE_LOCAL;
      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
                                    ieee_regno_to_genreg (info->abfd, v));
                                    ieee_regno_to_genreg (info->abfd, v));
 
 
    case 3:
    case 3:
      /* Static variable.  */
      /* Static variable.  */
      if (! ieee_require_asn (info, pp, &v))
      if (! ieee_require_asn (info, pp, &v))
        return FALSE;
        return FALSE;
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (type == NULL)
      if (type == NULL)
        type = debug_make_void_type (dhandle);
        type = debug_make_void_type (dhandle);
      if (info->blockstack.bsp <= info->blockstack.stack)
      if (info->blockstack.bsp <= info->blockstack.stack)
        blocktype = 0;
        blocktype = 0;
      else
      else
        blocktype = info->blockstack.bsp[-1].kind;
        blocktype = info->blockstack.bsp[-1].kind;
      if (pvar != NULL)
      if (pvar != NULL)
        {
        {
          if (blocktype == 4 || blocktype == 6)
          if (blocktype == 4 || blocktype == 6)
            pvar->kind = IEEE_LOCAL;
            pvar->kind = IEEE_LOCAL;
          else
          else
            pvar->kind = IEEE_STATIC;
            pvar->kind = IEEE_STATIC;
        }
        }
      return debug_record_variable (dhandle, namcopy, type,
      return debug_record_variable (dhandle, namcopy, type,
                                    (blocktype == 4 || blocktype == 6
                                    (blocktype == 4 || blocktype == 6
                                     ? DEBUG_LOCAL_STATIC
                                     ? DEBUG_LOCAL_STATIC
                                     : DEBUG_STATIC),
                                     : DEBUG_STATIC),
                                    v);
                                    v);
 
 
    case 4:
    case 4:
      /* External function.  We don't currently record these.  FIXME.  */
      /* External function.  We don't currently record these.  FIXME.  */
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_EXTERNAL;
        pvar->kind = IEEE_EXTERNAL;
      return TRUE;
      return TRUE;
 
 
    case 5:
    case 5:
      /* External variable.  We don't currently record these.  FIXME.  */
      /* External variable.  We don't currently record these.  FIXME.  */
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_EXTERNAL;
        pvar->kind = IEEE_EXTERNAL;
      return TRUE;
      return TRUE;
 
 
    case 7:
    case 7:
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_optional_number (info, pp, &v3, &present))
          || ! ieee_read_optional_number (info, pp, &v3, &present))
        return FALSE;
        return FALSE;
      if (present)
      if (present)
        {
        {
          if (! ieee_read_optional_number (info, pp, &v4, &present))
          if (! ieee_read_optional_number (info, pp, &v4, &present))
            return FALSE;
            return FALSE;
        }
        }
 
 
      /* We just ignore the two optional fields in v3 and v4, since
      /* We just ignore the two optional fields in v3 and v4, since
         they are not defined.  */
         they are not defined.  */
 
 
      if (! ieee_require_asn (info, pp, &v3))
      if (! ieee_require_asn (info, pp, &v3))
        return FALSE;
        return FALSE;
 
 
      /* We have no way to record the column number.  FIXME.  */
      /* We have no way to record the column number.  FIXME.  */
 
 
      return debug_record_line (dhandle, v, v3);
      return debug_record_line (dhandle, v, v3);
 
 
    case 8:
    case 8:
      /* Global variable.  */
      /* Global variable.  */
      if (! ieee_require_asn (info, pp, &v))
      if (! ieee_require_asn (info, pp, &v))
        return FALSE;
        return FALSE;
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (type == NULL)
      if (type == NULL)
        type = debug_make_void_type (dhandle);
        type = debug_make_void_type (dhandle);
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_GLOBAL;
        pvar->kind = IEEE_GLOBAL;
      return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
      return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
 
 
    case 9:
    case 9:
      /* Variable lifetime information.  */
      /* Variable lifetime information.  */
      if (! ieee_read_number (info, pp, &v))
      if (! ieee_read_number (info, pp, &v))
        return FALSE;
        return FALSE;
 
 
      /* We have no way to record this information.  FIXME.  */
      /* We have no way to record this information.  FIXME.  */
      return TRUE;
      return TRUE;
 
 
    case 10:
    case 10:
      /* Locked register.  The spec says that there are two required
      /* Locked register.  The spec says that there are two required
         fields, but at least on occasion the MRI compiler only emits
         fields, but at least on occasion the MRI compiler only emits
         one.  */
         one.  */
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_optional_number (info, pp, &v2, &present))
          || ! ieee_read_optional_number (info, pp, &v2, &present))
        return FALSE;
        return FALSE;
 
 
      /* I think this means a variable that is both in a register and
      /* I think this means a variable that is both in a register and
         a frame slot.  We ignore the frame slot.  FIXME.  */
         a frame slot.  We ignore the frame slot.  FIXME.  */
 
 
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      if (type == NULL)
      if (type == NULL)
        type = debug_make_void_type (dhandle);
        type = debug_make_void_type (dhandle);
      if (pvar != NULL)
      if (pvar != NULL)
        pvar->kind = IEEE_LOCAL;
        pvar->kind = IEEE_LOCAL;
      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
 
 
    case 11:
    case 11:
      /* Reserved for FORTRAN common.  */
      /* Reserved for FORTRAN common.  */
      ieee_error (info, atn_code_start, _("unsupported ATN11"));
      ieee_error (info, atn_code_start, _("unsupported ATN11"));
 
 
      /* Return TRUE to keep going.  */
      /* Return TRUE to keep going.  */
      return TRUE;
      return TRUE;
 
 
    case 12:
    case 12:
      /* Based variable.  */
      /* Based variable.  */
      v3 = 0;
      v3 = 0;
      v4 = 0x80;
      v4 = 0x80;
      v5 = 0;
      v5 = 0;
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_optional_number (info, pp, &v3, &present))
          || ! ieee_read_optional_number (info, pp, &v3, &present))
        return FALSE;
        return FALSE;
      if (present)
      if (present)
        {
        {
          if (! ieee_read_optional_number (info, pp, &v4, &present))
          if (! ieee_read_optional_number (info, pp, &v4, &present))
            return FALSE;
            return FALSE;
          if (present)
          if (present)
            {
            {
              if (! ieee_read_optional_number (info, pp, &v5, &present))
              if (! ieee_read_optional_number (info, pp, &v5, &present))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
 
 
      /* We have no way to record this information.  FIXME.  */
      /* We have no way to record this information.  FIXME.  */
 
 
      ieee_error (info, atn_code_start, _("unsupported ATN12"));
      ieee_error (info, atn_code_start, _("unsupported ATN12"));
 
 
      /* Return TRUE to keep going.  */
      /* Return TRUE to keep going.  */
      return TRUE;
      return TRUE;
 
 
    case 16:
    case 16:
      /* Constant.  The description of this that I have is ambiguous,
      /* Constant.  The description of this that I have is ambiguous,
         so I'm not going to try to implement it.  */
         so I'm not going to try to implement it.  */
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_optional_number (info, pp, &v2, &present))
          || ! ieee_read_optional_number (info, pp, &v2, &present))
        return FALSE;
        return FALSE;
      if (present)
      if (present)
        {
        {
          if (! ieee_read_optional_number (info, pp, &v2, &present))
          if (! ieee_read_optional_number (info, pp, &v2, &present))
            return FALSE;
            return FALSE;
          if (present)
          if (present)
            {
            {
              if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
              if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
 
 
      if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
      if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
        {
        {
          if (! ieee_require_asn (info, pp, &v3))
          if (! ieee_require_asn (info, pp, &v3))
            return FALSE;
            return FALSE;
        }
        }
 
 
      return TRUE;
      return TRUE;
 
 
    case 19:
    case 19:
      /* Static variable from assembler.  */
      /* Static variable from assembler.  */
      v2 = 0;
      v2 = 0;
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_optional_number (info, pp, &v2, &present)
          || ! ieee_read_optional_number (info, pp, &v2, &present)
          || ! ieee_require_asn (info, pp, &v3))
          || ! ieee_require_asn (info, pp, &v3))
        return FALSE;
        return FALSE;
      namcopy = savestring (name, namlen);
      namcopy = savestring (name, namlen);
      /* We don't really handle this correctly.  FIXME.  */
      /* We don't really handle this correctly.  FIXME.  */
      return debug_record_variable (dhandle, namcopy,
      return debug_record_variable (dhandle, namcopy,
                                    debug_make_void_type (dhandle),
                                    debug_make_void_type (dhandle),
                                    v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
                                    v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
                                    v3);
                                    v3);
 
 
    case 62:
    case 62:
      /* Procedure miscellaneous information.  */
      /* Procedure miscellaneous information.  */
    case 63:
    case 63:
      /* Variable miscellaneous information.  */
      /* Variable miscellaneous information.  */
    case 64:
    case 64:
      /* Module miscellaneous information.  */
      /* Module miscellaneous information.  */
      if (! ieee_read_number (info, pp, &v)
      if (! ieee_read_number (info, pp, &v)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_number (info, pp, &v2)
          || ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
          || ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
        return FALSE;
        return FALSE;
 
 
      if (atn_code == 62 && v == 80)
      if (atn_code == 62 && v == 80)
        {
        {
          if (present)
          if (present)
            {
            {
              ieee_error (info, atn_code_start,
              ieee_error (info, atn_code_start,
                          _("unexpected string in C++ misc"));
                          _("unexpected string in C++ misc"));
              return FALSE;
              return FALSE;
            }
            }
          return ieee_read_cxx_misc (info, pp, v2);
          return ieee_read_cxx_misc (info, pp, v2);
        }
        }
 
 
      /* We just ignore all of this stuff.  FIXME.  */
      /* We just ignore all of this stuff.  FIXME.  */
 
 
      for (; v2 > 0; --v2)
      for (; v2 > 0; --v2)
        {
        {
          switch ((ieee_record_enum_type) **pp)
          switch ((ieee_record_enum_type) **pp)
            {
            {
            default:
            default:
              ieee_error (info, *pp, _("bad misc record"));
              ieee_error (info, *pp, _("bad misc record"));
              return FALSE;
              return FALSE;
 
 
            case ieee_at_record_enum:
            case ieee_at_record_enum:
              if (! ieee_require_atn65 (info, pp, &name, &namlen))
              if (! ieee_require_atn65 (info, pp, &name, &namlen))
                return FALSE;
                return FALSE;
              break;
              break;
 
 
            case ieee_e2_first_byte_enum:
            case ieee_e2_first_byte_enum:
              if (! ieee_require_asn (info, pp, &v3))
              if (! ieee_require_asn (info, pp, &v3))
                return FALSE;
                return FALSE;
              break;
              break;
            }
            }
        }
        }
 
 
      return TRUE;
      return TRUE;
    }
    }
 
 
  /*NOTREACHED*/
  /*NOTREACHED*/
}
}
 
 
/* Handle C++ debugging miscellaneous records.  This is called for
/* Handle C++ debugging miscellaneous records.  This is called for
   procedure miscellaneous records of type 80.  */
   procedure miscellaneous records of type 80.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_cxx_misc (struct ieee_info *info, const bfd_byte **pp,
ieee_read_cxx_misc (struct ieee_info *info, const bfd_byte **pp,
                    unsigned long count)
                    unsigned long count)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  bfd_vma category;
  bfd_vma category;
 
 
  start = *pp;
  start = *pp;
 
 
  /* Get the category of C++ misc record.  */
  /* Get the category of C++ misc record.  */
  if (! ieee_require_asn (info, pp, &category))
  if (! ieee_require_asn (info, pp, &category))
    return FALSE;
    return FALSE;
  --count;
  --count;
 
 
  switch (category)
  switch (category)
    {
    {
    default:
    default:
      ieee_error (info, start, _("unrecognized C++ misc record"));
      ieee_error (info, start, _("unrecognized C++ misc record"));
      return FALSE;
      return FALSE;
 
 
    case 'T':
    case 'T':
      if (! ieee_read_cxx_class (info, pp, count))
      if (! ieee_read_cxx_class (info, pp, count))
        return FALSE;
        return FALSE;
      break;
      break;
 
 
    case 'M':
    case 'M':
      {
      {
        bfd_vma flags;
        bfd_vma flags;
        const char *name;
        const char *name;
        unsigned long namlen;
        unsigned long namlen;
 
 
        /* The IEEE spec indicates that the 'M' record only has a
        /* The IEEE spec indicates that the 'M' record only has a
           flags field.  The MRI compiler also emits the name of the
           flags field.  The MRI compiler also emits the name of the
           function.  */
           function.  */
 
 
        if (! ieee_require_asn (info, pp, &flags))
        if (! ieee_require_asn (info, pp, &flags))
          return FALSE;
          return FALSE;
        if (*pp < info->pend
        if (*pp < info->pend
            && (ieee_record_enum_type) **pp == ieee_at_record_enum)
            && (ieee_record_enum_type) **pp == ieee_at_record_enum)
          {
          {
            if (! ieee_require_atn65 (info, pp, &name, &namlen))
            if (! ieee_require_atn65 (info, pp, &name, &namlen))
              return FALSE;
              return FALSE;
          }
          }
 
 
        /* This is emitted for method functions, but I don't think we
        /* This is emitted for method functions, but I don't think we
           care very much.  It might help if it told us useful
           care very much.  It might help if it told us useful
           information like the class with which this function is
           information like the class with which this function is
           associated, but it doesn't, so it isn't helpful.  */
           associated, but it doesn't, so it isn't helpful.  */
      }
      }
      break;
      break;
 
 
    case 'B':
    case 'B':
      if (! ieee_read_cxx_defaults (info, pp, count))
      if (! ieee_read_cxx_defaults (info, pp, count))
        return FALSE;
        return FALSE;
      break;
      break;
 
 
    case 'z':
    case 'z':
      {
      {
        const char *name, *mangled, *class;
        const char *name, *mangled, *class;
        unsigned long namlen, mangledlen, classlen;
        unsigned long namlen, mangledlen, classlen;
        bfd_vma control;
        bfd_vma control;
 
 
        /* Pointer to member.  */
        /* Pointer to member.  */
 
 
        if (! ieee_require_atn65 (info, pp, &name, &namlen)
        if (! ieee_require_atn65 (info, pp, &name, &namlen)
            || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
            || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
            || ! ieee_require_atn65 (info, pp, &class, &classlen)
            || ! ieee_require_atn65 (info, pp, &class, &classlen)
            || ! ieee_require_asn (info, pp, &control))
            || ! ieee_require_asn (info, pp, &control))
          return FALSE;
          return FALSE;
 
 
        /* FIXME: We should now track down name and change its type.  */
        /* FIXME: We should now track down name and change its type.  */
      }
      }
      break;
      break;
 
 
    case 'R':
    case 'R':
      if (! ieee_read_reference (info, pp))
      if (! ieee_read_reference (info, pp))
        return FALSE;
        return FALSE;
      break;
      break;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Read a C++ class definition.  This is a pmisc type 80 record of
/* Read a C++ class definition.  This is a pmisc type 80 record of
   category 'T'.  */
   category 'T'.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_cxx_class (struct ieee_info *info, const bfd_byte **pp,
ieee_read_cxx_class (struct ieee_info *info, const bfd_byte **pp,
                     unsigned long count)
                     unsigned long count)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  bfd_vma class;
  bfd_vma class;
  const char *tag;
  const char *tag;
  unsigned long taglen;
  unsigned long taglen;
  struct ieee_tag *it;
  struct ieee_tag *it;
  void *dhandle;
  void *dhandle;
  debug_field *fields;
  debug_field *fields;
  unsigned int field_count, field_alloc;
  unsigned int field_count, field_alloc;
  debug_baseclass *baseclasses;
  debug_baseclass *baseclasses;
  unsigned int baseclasses_count, baseclasses_alloc;
  unsigned int baseclasses_count, baseclasses_alloc;
  const debug_field *structfields;
  const debug_field *structfields;
  struct ieee_method
  struct ieee_method
    {
    {
      const char *name;
      const char *name;
      unsigned long namlen;
      unsigned long namlen;
      debug_method_variant *variants;
      debug_method_variant *variants;
      unsigned count;
      unsigned count;
      unsigned int alloc;
      unsigned int alloc;
    } *methods;
    } *methods;
  unsigned int methods_count, methods_alloc;
  unsigned int methods_count, methods_alloc;
  debug_type vptrbase;
  debug_type vptrbase;
  bfd_boolean ownvptr;
  bfd_boolean ownvptr;
  debug_method *dmethods;
  debug_method *dmethods;
 
 
  start = *pp;
  start = *pp;
 
 
  if (! ieee_require_asn (info, pp, &class))
  if (! ieee_require_asn (info, pp, &class))
    return FALSE;
    return FALSE;
  --count;
  --count;
 
 
  if (! ieee_require_atn65 (info, pp, &tag, &taglen))
  if (! ieee_require_atn65 (info, pp, &tag, &taglen))
    return FALSE;
    return FALSE;
  --count;
  --count;
 
 
  /* Find the C struct with this name.  */
  /* Find the C struct with this name.  */
  for (it = info->tags; it != NULL; it = it->next)
  for (it = info->tags; it != NULL; it = it->next)
    if (it->name[0] == tag[0]
    if (it->name[0] == tag[0]
        && strncmp (it->name, tag, taglen) == 0
        && strncmp (it->name, tag, taglen) == 0
        && strlen (it->name) == taglen)
        && strlen (it->name) == taglen)
      break;
      break;
  if (it == NULL)
  if (it == NULL)
    {
    {
      ieee_error (info, start, _("undefined C++ object"));
      ieee_error (info, start, _("undefined C++ object"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  dhandle = info->dhandle;
  dhandle = info->dhandle;
 
 
  fields = NULL;
  fields = NULL;
  field_count = 0;
  field_count = 0;
  field_alloc = 0;
  field_alloc = 0;
  baseclasses = NULL;
  baseclasses = NULL;
  baseclasses_count = 0;
  baseclasses_count = 0;
  baseclasses_alloc = 0;
  baseclasses_alloc = 0;
  methods = NULL;
  methods = NULL;
  methods_count = 0;
  methods_count = 0;
  methods_alloc = 0;
  methods_alloc = 0;
  vptrbase = DEBUG_TYPE_NULL;
  vptrbase = DEBUG_TYPE_NULL;
  ownvptr = FALSE;
  ownvptr = FALSE;
 
 
  structfields = debug_get_fields (dhandle, it->type);
  structfields = debug_get_fields (dhandle, it->type);
 
 
  while (count > 0)
  while (count > 0)
    {
    {
      bfd_vma id;
      bfd_vma id;
      const bfd_byte *spec_start;
      const bfd_byte *spec_start;
 
 
      spec_start = *pp;
      spec_start = *pp;
 
 
      if (! ieee_require_asn (info, pp, &id))
      if (! ieee_require_asn (info, pp, &id))
        return FALSE;
        return FALSE;
      --count;
      --count;
 
 
      switch (id)
      switch (id)
        {
        {
        default:
        default:
          ieee_error (info, spec_start, _("unrecognized C++ object spec"));
          ieee_error (info, spec_start, _("unrecognized C++ object spec"));
          return FALSE;
          return FALSE;
 
 
        case 'b':
        case 'b':
          {
          {
            bfd_vma flags, cinline;
            bfd_vma flags, cinline;
            const char *basename, *fieldname;
            const char *basename, *fieldname;
            unsigned long baselen, fieldlen;
            unsigned long baselen, fieldlen;
            char *basecopy;
            char *basecopy;
            debug_type basetype;
            debug_type basetype;
            bfd_vma bitpos;
            bfd_vma bitpos;
            bfd_boolean virtualp;
            bfd_boolean virtualp;
            enum debug_visibility visibility;
            enum debug_visibility visibility;
            debug_baseclass baseclass;
            debug_baseclass baseclass;
 
 
            /* This represents a base or friend class.  */
            /* This represents a base or friend class.  */
 
 
            if (! ieee_require_asn (info, pp, &flags)
            if (! ieee_require_asn (info, pp, &flags)
                || ! ieee_require_atn65 (info, pp, &basename, &baselen)
                || ! ieee_require_atn65 (info, pp, &basename, &baselen)
                || ! ieee_require_asn (info, pp, &cinline)
                || ! ieee_require_asn (info, pp, &cinline)
                || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
                || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
              return FALSE;
              return FALSE;
            count -= 4;
            count -= 4;
 
 
            /* We have no way of recording friend information, so we
            /* We have no way of recording friend information, so we
               just ignore it.  */
               just ignore it.  */
            if ((flags & BASEFLAGS_FRIEND) != 0)
            if ((flags & BASEFLAGS_FRIEND) != 0)
              break;
              break;
 
 
            /* I assume that either all of the members of the
            /* I assume that either all of the members of the
               baseclass are included in the object, starting at the
               baseclass are included in the object, starting at the
               beginning of the object, or that none of them are
               beginning of the object, or that none of them are
               included.  */
               included.  */
 
 
            if ((fieldlen == 0) == (cinline == 0))
            if ((fieldlen == 0) == (cinline == 0))
              {
              {
                ieee_error (info, start, _("unsupported C++ object type"));
                ieee_error (info, start, _("unsupported C++ object type"));
                return FALSE;
                return FALSE;
              }
              }
 
 
            basecopy = savestring (basename, baselen);
            basecopy = savestring (basename, baselen);
            basetype = debug_find_tagged_type (dhandle, basecopy,
            basetype = debug_find_tagged_type (dhandle, basecopy,
                                               DEBUG_KIND_ILLEGAL);
                                               DEBUG_KIND_ILLEGAL);
            free (basecopy);
            free (basecopy);
            if (basetype == DEBUG_TYPE_NULL)
            if (basetype == DEBUG_TYPE_NULL)
              {
              {
                ieee_error (info, start, _("C++ base class not defined"));
                ieee_error (info, start, _("C++ base class not defined"));
                return FALSE;
                return FALSE;
              }
              }
 
 
            if (fieldlen == 0)
            if (fieldlen == 0)
              bitpos = 0;
              bitpos = 0;
            else
            else
              {
              {
                const debug_field *pf;
                const debug_field *pf;
 
 
                if (structfields == NULL)
                if (structfields == NULL)
                  {
                  {
                    ieee_error (info, start, _("C++ object has no fields"));
                    ieee_error (info, start, _("C++ object has no fields"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
                for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
                  {
                  {
                    const char *fname;
                    const char *fname;
 
 
                    fname = debug_get_field_name (dhandle, *pf);
                    fname = debug_get_field_name (dhandle, *pf);
                    if (fname == NULL)
                    if (fname == NULL)
                      return FALSE;
                      return FALSE;
                    if (fname[0] == fieldname[0]
                    if (fname[0] == fieldname[0]
                        && strncmp (fname, fieldname, fieldlen) == 0
                        && strncmp (fname, fieldname, fieldlen) == 0
                        && strlen (fname) == fieldlen)
                        && strlen (fname) == fieldlen)
                      break;
                      break;
                  }
                  }
                if (*pf == DEBUG_FIELD_NULL)
                if (*pf == DEBUG_FIELD_NULL)
                  {
                  {
                    ieee_error (info, start,
                    ieee_error (info, start,
                                _("C++ base class not found in container"));
                                _("C++ base class not found in container"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                bitpos = debug_get_field_bitpos (dhandle, *pf);
                bitpos = debug_get_field_bitpos (dhandle, *pf);
              }
              }
 
 
            if ((flags & BASEFLAGS_VIRTUAL) != 0)
            if ((flags & BASEFLAGS_VIRTUAL) != 0)
              virtualp = TRUE;
              virtualp = TRUE;
            else
            else
              virtualp = FALSE;
              virtualp = FALSE;
            if ((flags & BASEFLAGS_PRIVATE) != 0)
            if ((flags & BASEFLAGS_PRIVATE) != 0)
              visibility = DEBUG_VISIBILITY_PRIVATE;
              visibility = DEBUG_VISIBILITY_PRIVATE;
            else
            else
              visibility = DEBUG_VISIBILITY_PUBLIC;
              visibility = DEBUG_VISIBILITY_PUBLIC;
 
 
            baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
            baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
                                              virtualp, visibility);
                                              virtualp, visibility);
            if (baseclass == DEBUG_BASECLASS_NULL)
            if (baseclass == DEBUG_BASECLASS_NULL)
              return FALSE;
              return FALSE;
 
 
            if (baseclasses_count + 1 >= baseclasses_alloc)
            if (baseclasses_count + 1 >= baseclasses_alloc)
              {
              {
                baseclasses_alloc += 10;
                baseclasses_alloc += 10;
                baseclasses = ((debug_baseclass *)
                baseclasses = ((debug_baseclass *)
                               xrealloc (baseclasses,
                               xrealloc (baseclasses,
                                         (baseclasses_alloc
                                         (baseclasses_alloc
                                          * sizeof *baseclasses)));
                                          * sizeof *baseclasses)));
              }
              }
 
 
            baseclasses[baseclasses_count] = baseclass;
            baseclasses[baseclasses_count] = baseclass;
            ++baseclasses_count;
            ++baseclasses_count;
            baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
            baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
          }
          }
          break;
          break;
 
 
        case 'd':
        case 'd':
          {
          {
            bfd_vma flags;
            bfd_vma flags;
            const char *fieldname, *mangledname;
            const char *fieldname, *mangledname;
            unsigned long fieldlen, mangledlen;
            unsigned long fieldlen, mangledlen;
            char *fieldcopy;
            char *fieldcopy;
            bfd_boolean staticp;
            bfd_boolean staticp;
            debug_type ftype;
            debug_type ftype;
            const debug_field *pf = NULL;
            const debug_field *pf = NULL;
            enum debug_visibility visibility;
            enum debug_visibility visibility;
            debug_field field;
            debug_field field;
 
 
            /* This represents a data member.  */
            /* This represents a data member.  */
 
 
            if (! ieee_require_asn (info, pp, &flags)
            if (! ieee_require_asn (info, pp, &flags)
                || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
                || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
                || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
                || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
              return FALSE;
              return FALSE;
            count -= 3;
            count -= 3;
 
 
            fieldcopy = savestring (fieldname, fieldlen);
            fieldcopy = savestring (fieldname, fieldlen);
 
 
            staticp = (flags & CXXFLAGS_STATIC) != 0 ? TRUE : FALSE;
            staticp = (flags & CXXFLAGS_STATIC) != 0 ? TRUE : FALSE;
 
 
            if (staticp)
            if (staticp)
              {
              {
                struct ieee_var *pv, *pvend;
                struct ieee_var *pv, *pvend;
 
 
                /* See if we can find a definition for this variable.  */
                /* See if we can find a definition for this variable.  */
                pv = info->vars.vars;
                pv = info->vars.vars;
                pvend = pv + info->vars.alloc;
                pvend = pv + info->vars.alloc;
                for (; pv < pvend; pv++)
                for (; pv < pvend; pv++)
                  if (pv->namlen == mangledlen
                  if (pv->namlen == mangledlen
                      && strncmp (pv->name, mangledname, mangledlen) == 0)
                      && strncmp (pv->name, mangledname, mangledlen) == 0)
                    break;
                    break;
                if (pv < pvend)
                if (pv < pvend)
                  ftype = pv->type;
                  ftype = pv->type;
                else
                else
                  {
                  {
                    /* This can happen if the variable is never used.  */
                    /* This can happen if the variable is never used.  */
                    ftype = ieee_builtin_type (info, start,
                    ftype = ieee_builtin_type (info, start,
                                               (unsigned int) builtin_void);
                                               (unsigned int) builtin_void);
                  }
                  }
              }
              }
            else
            else
              {
              {
                unsigned int findx;
                unsigned int findx;
 
 
                if (structfields == NULL)
                if (structfields == NULL)
                  {
                  {
                    ieee_error (info, start, _("C++ object has no fields"));
                    ieee_error (info, start, _("C++ object has no fields"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                for (pf = structfields, findx = 0;
                for (pf = structfields, findx = 0;
                     *pf != DEBUG_FIELD_NULL;
                     *pf != DEBUG_FIELD_NULL;
                     pf++, findx++)
                     pf++, findx++)
                  {
                  {
                    const char *fname;
                    const char *fname;
 
 
                    fname = debug_get_field_name (dhandle, *pf);
                    fname = debug_get_field_name (dhandle, *pf);
                    if (fname == NULL)
                    if (fname == NULL)
                      return FALSE;
                      return FALSE;
                    if (fname[0] == mangledname[0]
                    if (fname[0] == mangledname[0]
                        && strncmp (fname, mangledname, mangledlen) == 0
                        && strncmp (fname, mangledname, mangledlen) == 0
                        && strlen (fname) == mangledlen)
                        && strlen (fname) == mangledlen)
                      break;
                      break;
                  }
                  }
                if (*pf == DEBUG_FIELD_NULL)
                if (*pf == DEBUG_FIELD_NULL)
                  {
                  {
                    ieee_error (info, start,
                    ieee_error (info, start,
                                _("C++ data member not found in container"));
                                _("C++ data member not found in container"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                ftype = debug_get_field_type (dhandle, *pf);
                ftype = debug_get_field_type (dhandle, *pf);
 
 
                if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
                if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
                  {
                  {
                    /* We might need to convert this field into a
                    /* We might need to convert this field into a
                       reference type later on, so make it an indirect
                       reference type later on, so make it an indirect
                       type.  */
                       type.  */
                    if (it->fslots == NULL)
                    if (it->fslots == NULL)
                      {
                      {
                        unsigned int fcnt;
                        unsigned int fcnt;
                        const debug_field *pfcnt;
                        const debug_field *pfcnt;
 
 
                        fcnt = 0;
                        fcnt = 0;
                        for (pfcnt = structfields;
                        for (pfcnt = structfields;
                             *pfcnt != DEBUG_FIELD_NULL;
                             *pfcnt != DEBUG_FIELD_NULL;
                             pfcnt++)
                             pfcnt++)
                          ++fcnt;
                          ++fcnt;
                        it->fslots = ((debug_type *)
                        it->fslots = ((debug_type *)
                                      xmalloc (fcnt * sizeof *it->fslots));
                                      xmalloc (fcnt * sizeof *it->fslots));
                        memset (it->fslots, 0,
                        memset (it->fslots, 0,
                                fcnt * sizeof *it->fslots);
                                fcnt * sizeof *it->fslots);
                      }
                      }
 
 
                    if (ftype == DEBUG_TYPE_NULL)
                    if (ftype == DEBUG_TYPE_NULL)
                      return FALSE;
                      return FALSE;
                    it->fslots[findx] = ftype;
                    it->fslots[findx] = ftype;
                    ftype = debug_make_indirect_type (dhandle,
                    ftype = debug_make_indirect_type (dhandle,
                                                      it->fslots + findx,
                                                      it->fslots + findx,
                                                      (const char *) NULL);
                                                      (const char *) NULL);
                  }
                  }
              }
              }
            if (ftype == DEBUG_TYPE_NULL)
            if (ftype == DEBUG_TYPE_NULL)
              return FALSE;
              return FALSE;
 
 
            switch (flags & CXXFLAGS_VISIBILITY)
            switch (flags & CXXFLAGS_VISIBILITY)
              {
              {
              default:
              default:
                ieee_error (info, start, _("unknown C++ visibility"));
                ieee_error (info, start, _("unknown C++ visibility"));
                return FALSE;
                return FALSE;
 
 
              case CXXFLAGS_VISIBILITY_PUBLIC:
              case CXXFLAGS_VISIBILITY_PUBLIC:
                visibility = DEBUG_VISIBILITY_PUBLIC;
                visibility = DEBUG_VISIBILITY_PUBLIC;
                break;
                break;
 
 
              case CXXFLAGS_VISIBILITY_PRIVATE:
              case CXXFLAGS_VISIBILITY_PRIVATE:
                visibility = DEBUG_VISIBILITY_PRIVATE;
                visibility = DEBUG_VISIBILITY_PRIVATE;
                break;
                break;
 
 
              case CXXFLAGS_VISIBILITY_PROTECTED:
              case CXXFLAGS_VISIBILITY_PROTECTED:
                visibility = DEBUG_VISIBILITY_PROTECTED;
                visibility = DEBUG_VISIBILITY_PROTECTED;
                break;
                break;
              }
              }
 
 
            if (staticp)
            if (staticp)
              {
              {
                char *mangledcopy;
                char *mangledcopy;
 
 
                mangledcopy = savestring (mangledname, mangledlen);
                mangledcopy = savestring (mangledname, mangledlen);
 
 
                field = debug_make_static_member (dhandle, fieldcopy,
                field = debug_make_static_member (dhandle, fieldcopy,
                                                  ftype, mangledcopy,
                                                  ftype, mangledcopy,
                                                  visibility);
                                                  visibility);
              }
              }
            else
            else
              {
              {
                bfd_vma bitpos, bitsize;
                bfd_vma bitpos, bitsize;
 
 
                bitpos = debug_get_field_bitpos (dhandle, *pf);
                bitpos = debug_get_field_bitpos (dhandle, *pf);
                bitsize = debug_get_field_bitsize (dhandle, *pf);
                bitsize = debug_get_field_bitsize (dhandle, *pf);
                if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
                if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
                  {
                  {
                    ieee_error (info, start, _("bad C++ field bit pos or size"));
                    ieee_error (info, start, _("bad C++ field bit pos or size"));
                    return FALSE;
                    return FALSE;
                  }
                  }
                field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
                field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
                                          bitsize, visibility);
                                          bitsize, visibility);
              }
              }
 
 
            if (field == DEBUG_FIELD_NULL)
            if (field == DEBUG_FIELD_NULL)
              return FALSE;
              return FALSE;
 
 
            if (field_count + 1 >= field_alloc)
            if (field_count + 1 >= field_alloc)
              {
              {
                field_alloc += 10;
                field_alloc += 10;
                fields = ((debug_field *)
                fields = ((debug_field *)
                          xrealloc (fields, field_alloc * sizeof *fields));
                          xrealloc (fields, field_alloc * sizeof *fields));
              }
              }
 
 
            fields[field_count] = field;
            fields[field_count] = field;
            ++field_count;
            ++field_count;
            fields[field_count] = DEBUG_FIELD_NULL;
            fields[field_count] = DEBUG_FIELD_NULL;
          }
          }
          break;
          break;
 
 
        case 'm':
        case 'm':
        case 'v':
        case 'v':
          {
          {
            bfd_vma flags, voffset, control;
            bfd_vma flags, voffset, control;
            const char *name, *mangled;
            const char *name, *mangled;
            unsigned long namlen, mangledlen;
            unsigned long namlen, mangledlen;
            struct ieee_var *pv, *pvend;
            struct ieee_var *pv, *pvend;
            debug_type type;
            debug_type type;
            enum debug_visibility visibility;
            enum debug_visibility visibility;
            bfd_boolean constp, volatilep;
            bfd_boolean constp, volatilep;
            char *mangledcopy;
            char *mangledcopy;
            debug_method_variant mv;
            debug_method_variant mv;
            struct ieee_method *meth;
            struct ieee_method *meth;
            unsigned int im;
            unsigned int im;
 
 
            if (! ieee_require_asn (info, pp, &flags)
            if (! ieee_require_asn (info, pp, &flags)
                || ! ieee_require_atn65 (info, pp, &name, &namlen)
                || ! ieee_require_atn65 (info, pp, &name, &namlen)
                || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
                || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
              return FALSE;
              return FALSE;
            count -= 3;
            count -= 3;
            if (id != 'v')
            if (id != 'v')
              voffset = 0;
              voffset = 0;
            else
            else
              {
              {
                if (! ieee_require_asn (info, pp, &voffset))
                if (! ieee_require_asn (info, pp, &voffset))
                  return FALSE;
                  return FALSE;
                --count;
                --count;
              }
              }
            if (! ieee_require_asn (info, pp, &control))
            if (! ieee_require_asn (info, pp, &control))
              return FALSE;
              return FALSE;
            --count;
            --count;
 
 
            /* We just ignore the control information.  */
            /* We just ignore the control information.  */
 
 
            /* We have no way to represent friend information, so we
            /* We have no way to represent friend information, so we
               just ignore it.  */
               just ignore it.  */
            if ((flags & CXXFLAGS_FRIEND) != 0)
            if ((flags & CXXFLAGS_FRIEND) != 0)
              break;
              break;
 
 
            /* We should already have seen a type for the function.  */
            /* We should already have seen a type for the function.  */
            pv = info->vars.vars;
            pv = info->vars.vars;
            pvend = pv + info->vars.alloc;
            pvend = pv + info->vars.alloc;
            for (; pv < pvend; pv++)
            for (; pv < pvend; pv++)
              if (pv->namlen == mangledlen
              if (pv->namlen == mangledlen
                  && strncmp (pv->name, mangled, mangledlen) == 0)
                  && strncmp (pv->name, mangled, mangledlen) == 0)
                break;
                break;
 
 
            if (pv >= pvend)
            if (pv >= pvend)
              {
              {
                /* We won't have type information for this function if
                /* We won't have type information for this function if
                   it is not included in this file.  We don't try to
                   it is not included in this file.  We don't try to
                   handle this case.  FIXME.  */
                   handle this case.  FIXME.  */
                type = (debug_make_function_type
                type = (debug_make_function_type
                        (dhandle,
                        (dhandle,
                         ieee_builtin_type (info, start,
                         ieee_builtin_type (info, start,
                                            (unsigned int) builtin_void),
                                            (unsigned int) builtin_void),
                         (debug_type *) NULL,
                         (debug_type *) NULL,
                         FALSE));
                         FALSE));
              }
              }
            else
            else
              {
              {
                debug_type return_type;
                debug_type return_type;
                const debug_type *arg_types;
                const debug_type *arg_types;
                bfd_boolean varargs;
                bfd_boolean varargs;
 
 
                if (debug_get_type_kind (dhandle, pv->type)
                if (debug_get_type_kind (dhandle, pv->type)
                    != DEBUG_KIND_FUNCTION)
                    != DEBUG_KIND_FUNCTION)
                  {
                  {
                    ieee_error (info, start,
                    ieee_error (info, start,
                                _("bad type for C++ method function"));
                                _("bad type for C++ method function"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                return_type = debug_get_return_type (dhandle, pv->type);
                return_type = debug_get_return_type (dhandle, pv->type);
                arg_types = debug_get_parameter_types (dhandle, pv->type,
                arg_types = debug_get_parameter_types (dhandle, pv->type,
                                                       &varargs);
                                                       &varargs);
                if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
                if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
                  {
                  {
                    ieee_error (info, start,
                    ieee_error (info, start,
                                _("no type information for C++ method function"));
                                _("no type information for C++ method function"));
                    return FALSE;
                    return FALSE;
                  }
                  }
 
 
                type = debug_make_method_type (dhandle, return_type, it->type,
                type = debug_make_method_type (dhandle, return_type, it->type,
                                               (debug_type *) arg_types,
                                               (debug_type *) arg_types,
                                               varargs);
                                               varargs);
              }
              }
            if (type == DEBUG_TYPE_NULL)
            if (type == DEBUG_TYPE_NULL)
              return FALSE;
              return FALSE;
 
 
            switch (flags & CXXFLAGS_VISIBILITY)
            switch (flags & CXXFLAGS_VISIBILITY)
              {
              {
              default:
              default:
                ieee_error (info, start, _("unknown C++ visibility"));
                ieee_error (info, start, _("unknown C++ visibility"));
                return FALSE;
                return FALSE;
 
 
              case CXXFLAGS_VISIBILITY_PUBLIC:
              case CXXFLAGS_VISIBILITY_PUBLIC:
                visibility = DEBUG_VISIBILITY_PUBLIC;
                visibility = DEBUG_VISIBILITY_PUBLIC;
                break;
                break;
 
 
              case CXXFLAGS_VISIBILITY_PRIVATE:
              case CXXFLAGS_VISIBILITY_PRIVATE:
                visibility = DEBUG_VISIBILITY_PRIVATE;
                visibility = DEBUG_VISIBILITY_PRIVATE;
                break;
                break;
 
 
              case CXXFLAGS_VISIBILITY_PROTECTED:
              case CXXFLAGS_VISIBILITY_PROTECTED:
                visibility = DEBUG_VISIBILITY_PROTECTED;
                visibility = DEBUG_VISIBILITY_PROTECTED;
                break;
                break;
              }
              }
 
 
            constp = (flags & CXXFLAGS_CONST) != 0 ? TRUE : FALSE;
            constp = (flags & CXXFLAGS_CONST) != 0 ? TRUE : FALSE;
            volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? TRUE : FALSE;
            volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? TRUE : FALSE;
 
 
            mangledcopy = savestring (mangled, mangledlen);
            mangledcopy = savestring (mangled, mangledlen);
 
 
            if ((flags & CXXFLAGS_STATIC) != 0)
            if ((flags & CXXFLAGS_STATIC) != 0)
              {
              {
                if (id == 'v')
                if (id == 'v')
                  {
                  {
                    ieee_error (info, start, _("C++ static virtual method"));
                    ieee_error (info, start, _("C++ static virtual method"));
                    return FALSE;
                    return FALSE;
                  }
                  }
                mv = debug_make_static_method_variant (dhandle, mangledcopy,
                mv = debug_make_static_method_variant (dhandle, mangledcopy,
                                                       type, visibility,
                                                       type, visibility,
                                                       constp, volatilep);
                                                       constp, volatilep);
              }
              }
            else
            else
              {
              {
                debug_type vcontext;
                debug_type vcontext;
 
 
                if (id != 'v')
                if (id != 'v')
                  vcontext = DEBUG_TYPE_NULL;
                  vcontext = DEBUG_TYPE_NULL;
                else
                else
                  {
                  {
                    /* FIXME: How can we calculate this correctly?  */
                    /* FIXME: How can we calculate this correctly?  */
                    vcontext = it->type;
                    vcontext = it->type;
                  }
                  }
                mv = debug_make_method_variant (dhandle, mangledcopy, type,
                mv = debug_make_method_variant (dhandle, mangledcopy, type,
                                                visibility, constp,
                                                visibility, constp,
                                                volatilep, voffset,
                                                volatilep, voffset,
                                                vcontext);
                                                vcontext);
              }
              }
            if (mv == DEBUG_METHOD_VARIANT_NULL)
            if (mv == DEBUG_METHOD_VARIANT_NULL)
              return FALSE;
              return FALSE;
 
 
            for (meth = methods, im = 0; im < methods_count; meth++, im++)
            for (meth = methods, im = 0; im < methods_count; meth++, im++)
              if (meth->namlen == namlen
              if (meth->namlen == namlen
                  && strncmp (meth->name, name, namlen) == 0)
                  && strncmp (meth->name, name, namlen) == 0)
                break;
                break;
            if (im >= methods_count)
            if (im >= methods_count)
              {
              {
                if (methods_count >= methods_alloc)
                if (methods_count >= methods_alloc)
                  {
                  {
                    methods_alloc += 10;
                    methods_alloc += 10;
                    methods = ((struct ieee_method *)
                    methods = ((struct ieee_method *)
                               xrealloc (methods,
                               xrealloc (methods,
                                         methods_alloc * sizeof *methods));
                                         methods_alloc * sizeof *methods));
                  }
                  }
                methods[methods_count].name = name;
                methods[methods_count].name = name;
                methods[methods_count].namlen = namlen;
                methods[methods_count].namlen = namlen;
                methods[methods_count].variants = NULL;
                methods[methods_count].variants = NULL;
                methods[methods_count].count = 0;
                methods[methods_count].count = 0;
                methods[methods_count].alloc = 0;
                methods[methods_count].alloc = 0;
                meth = methods + methods_count;
                meth = methods + methods_count;
                ++methods_count;
                ++methods_count;
              }
              }
 
 
            if (meth->count + 1 >= meth->alloc)
            if (meth->count + 1 >= meth->alloc)
              {
              {
                meth->alloc += 10;
                meth->alloc += 10;
                meth->variants = ((debug_method_variant *)
                meth->variants = ((debug_method_variant *)
                                  xrealloc (meth->variants,
                                  xrealloc (meth->variants,
                                            (meth->alloc
                                            (meth->alloc
                                             * sizeof *meth->variants)));
                                             * sizeof *meth->variants)));
              }
              }
 
 
            meth->variants[meth->count] = mv;
            meth->variants[meth->count] = mv;
            ++meth->count;
            ++meth->count;
            meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
            meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
          }
          }
          break;
          break;
 
 
        case 'o':
        case 'o':
          {
          {
            bfd_vma spec;
            bfd_vma spec;
 
 
            /* We have no way to store this information, so we just
            /* We have no way to store this information, so we just
               ignore it.  */
               ignore it.  */
            if (! ieee_require_asn (info, pp, &spec))
            if (! ieee_require_asn (info, pp, &spec))
              return FALSE;
              return FALSE;
            --count;
            --count;
            if ((spec & 4) != 0)
            if ((spec & 4) != 0)
              {
              {
                const char *filename;
                const char *filename;
                unsigned long filenamlen;
                unsigned long filenamlen;
                bfd_vma lineno;
                bfd_vma lineno;
 
 
                if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
                if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
                    || ! ieee_require_asn (info, pp, &lineno))
                    || ! ieee_require_asn (info, pp, &lineno))
                  return FALSE;
                  return FALSE;
                count -= 2;
                count -= 2;
              }
              }
            else if ((spec & 8) != 0)
            else if ((spec & 8) != 0)
              {
              {
                const char *mangled;
                const char *mangled;
                unsigned long mangledlen;
                unsigned long mangledlen;
 
 
                if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
                if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
                  return FALSE;
                  return FALSE;
                --count;
                --count;
              }
              }
            else
            else
              {
              {
                ieee_error (info, start,
                ieee_error (info, start,
                            _("unrecognized C++ object overhead spec"));
                            _("unrecognized C++ object overhead spec"));
                return FALSE;
                return FALSE;
              }
              }
          }
          }
          break;
          break;
 
 
        case 'z':
        case 'z':
          {
          {
            const char *vname, *basename;
            const char *vname, *basename;
            unsigned long vnamelen, baselen;
            unsigned long vnamelen, baselen;
            bfd_vma vsize, control;
            bfd_vma vsize, control;
 
 
            /* A virtual table pointer.  */
            /* A virtual table pointer.  */
 
 
            if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
            if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
                || ! ieee_require_asn (info, pp, &vsize)
                || ! ieee_require_asn (info, pp, &vsize)
                || ! ieee_require_atn65 (info, pp, &basename, &baselen)
                || ! ieee_require_atn65 (info, pp, &basename, &baselen)
                || ! ieee_require_asn (info, pp, &control))
                || ! ieee_require_asn (info, pp, &control))
              return FALSE;
              return FALSE;
            count -= 4;
            count -= 4;
 
 
            /* We just ignore the control number.  We don't care what
            /* We just ignore the control number.  We don't care what
               the virtual table name is.  We have no way to store the
               the virtual table name is.  We have no way to store the
               virtual table size, and I don't think we care anyhow.  */
               virtual table size, and I don't think we care anyhow.  */
 
 
            /* FIXME: We can't handle multiple virtual table pointers.  */
            /* FIXME: We can't handle multiple virtual table pointers.  */
 
 
            if (baselen == 0)
            if (baselen == 0)
              ownvptr = TRUE;
              ownvptr = TRUE;
            else
            else
              {
              {
                char *basecopy;
                char *basecopy;
 
 
                basecopy = savestring (basename, baselen);
                basecopy = savestring (basename, baselen);
                vptrbase = debug_find_tagged_type (dhandle, basecopy,
                vptrbase = debug_find_tagged_type (dhandle, basecopy,
                                                   DEBUG_KIND_ILLEGAL);
                                                   DEBUG_KIND_ILLEGAL);
                free (basecopy);
                free (basecopy);
                if (vptrbase == DEBUG_TYPE_NULL)
                if (vptrbase == DEBUG_TYPE_NULL)
                  {
                  {
                    ieee_error (info, start, _("undefined C++ vtable"));
                    ieee_error (info, start, _("undefined C++ vtable"));
                    return FALSE;
                    return FALSE;
                  }
                  }
              }
              }
          }
          }
          break;
          break;
        }
        }
    }
    }
 
 
  /* Now that we have seen all the method variants, we can call
  /* Now that we have seen all the method variants, we can call
     debug_make_method for each one.  */
     debug_make_method for each one.  */
 
 
  if (methods_count == 0)
  if (methods_count == 0)
    dmethods = NULL;
    dmethods = NULL;
  else
  else
    {
    {
      unsigned int i;
      unsigned int i;
 
 
      dmethods = ((debug_method *)
      dmethods = ((debug_method *)
                  xmalloc ((methods_count + 1) * sizeof *dmethods));
                  xmalloc ((methods_count + 1) * sizeof *dmethods));
      for (i = 0; i < methods_count; i++)
      for (i = 0; i < methods_count; i++)
        {
        {
          char *namcopy;
          char *namcopy;
 
 
          namcopy = savestring (methods[i].name, methods[i].namlen);
          namcopy = savestring (methods[i].name, methods[i].namlen);
          dmethods[i] = debug_make_method (dhandle, namcopy,
          dmethods[i] = debug_make_method (dhandle, namcopy,
                                           methods[i].variants);
                                           methods[i].variants);
          if (dmethods[i] == DEBUG_METHOD_NULL)
          if (dmethods[i] == DEBUG_METHOD_NULL)
            return FALSE;
            return FALSE;
        }
        }
      dmethods[i] = DEBUG_METHOD_NULL;
      dmethods[i] = DEBUG_METHOD_NULL;
      free (methods);
      free (methods);
    }
    }
 
 
  /* The struct type was created as an indirect type pointing at
  /* The struct type was created as an indirect type pointing at
     it->slot.  We update it->slot to automatically update all
     it->slot.  We update it->slot to automatically update all
     references to this struct.  */
     references to this struct.  */
  it->slot = debug_make_object_type (dhandle,
  it->slot = debug_make_object_type (dhandle,
                                     class != 'u',
                                     class != 'u',
                                     debug_get_type_size (dhandle,
                                     debug_get_type_size (dhandle,
                                                          it->slot),
                                                          it->slot),
                                     fields, baseclasses, dmethods,
                                     fields, baseclasses, dmethods,
                                     vptrbase, ownvptr);
                                     vptrbase, ownvptr);
  if (it->slot == DEBUG_TYPE_NULL)
  if (it->slot == DEBUG_TYPE_NULL)
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Read C++ default argument value and reference type information.  */
/* Read C++ default argument value and reference type information.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_cxx_defaults (struct ieee_info *info, const bfd_byte **pp,
ieee_read_cxx_defaults (struct ieee_info *info, const bfd_byte **pp,
                        unsigned long count)
                        unsigned long count)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  const char *fnname;
  const char *fnname;
  unsigned long fnlen;
  unsigned long fnlen;
  bfd_vma defcount;
  bfd_vma defcount;
 
 
  start = *pp;
  start = *pp;
 
 
  /* Giving the function name before the argument count is an addendum
  /* Giving the function name before the argument count is an addendum
     to the spec.  The function name is demangled, though, so this
     to the spec.  The function name is demangled, though, so this
     record must always refer to the current function.  */
     record must always refer to the current function.  */
 
 
  if (info->blockstack.bsp <= info->blockstack.stack
  if (info->blockstack.bsp <= info->blockstack.stack
      || info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
      || info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
    {
    {
      ieee_error (info, start, _("C++ default values not in a function"));
      ieee_error (info, start, _("C++ default values not in a function"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
  if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
      || ! ieee_require_asn (info, pp, &defcount))
      || ! ieee_require_asn (info, pp, &defcount))
    return FALSE;
    return FALSE;
  count -= 2;
  count -= 2;
 
 
  while (defcount-- > 0)
  while (defcount-- > 0)
    {
    {
      bfd_vma type, val;
      bfd_vma type, val;
      const char *strval;
      const char *strval;
      unsigned long strvallen;
      unsigned long strvallen;
 
 
      if (! ieee_require_asn (info, pp, &type))
      if (! ieee_require_asn (info, pp, &type))
        return FALSE;
        return FALSE;
      --count;
      --count;
 
 
      switch (type)
      switch (type)
        {
        {
        case 0:
        case 0:
        case 4:
        case 4:
          break;
          break;
 
 
        case 1:
        case 1:
        case 2:
        case 2:
          if (! ieee_require_asn (info, pp, &val))
          if (! ieee_require_asn (info, pp, &val))
            return FALSE;
            return FALSE;
          --count;
          --count;
          break;
          break;
 
 
        case 3:
        case 3:
        case 7:
        case 7:
          if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
          if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
            return FALSE;
            return FALSE;
          --count;
          --count;
          break;
          break;
 
 
        default:
        default:
          ieee_error (info, start, _("unrecognized C++ default type"));
          ieee_error (info, start, _("unrecognized C++ default type"));
          return FALSE;
          return FALSE;
        }
        }
 
 
      /* We have no way to record the default argument values, so we
      /* We have no way to record the default argument values, so we
         just ignore them.  FIXME.  */
         just ignore them.  FIXME.  */
    }
    }
 
 
  /* Any remaining arguments are indices of parameters that are really
  /* Any remaining arguments are indices of parameters that are really
     reference type.  */
     reference type.  */
  if (count > 0)
  if (count > 0)
    {
    {
      void *dhandle;
      void *dhandle;
      debug_type *arg_slots;
      debug_type *arg_slots;
 
 
      dhandle = info->dhandle;
      dhandle = info->dhandle;
      arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
      arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
      while (count-- > 0)
      while (count-- > 0)
        {
        {
          bfd_vma indx;
          bfd_vma indx;
          debug_type target;
          debug_type target;
 
 
          if (! ieee_require_asn (info, pp, &indx))
          if (! ieee_require_asn (info, pp, &indx))
            return FALSE;
            return FALSE;
          /* The index is 1 based.  */
          /* The index is 1 based.  */
          --indx;
          --indx;
          if (arg_slots == NULL
          if (arg_slots == NULL
              || arg_slots[indx] == DEBUG_TYPE_NULL
              || arg_slots[indx] == DEBUG_TYPE_NULL
              || (debug_get_type_kind (dhandle, arg_slots[indx])
              || (debug_get_type_kind (dhandle, arg_slots[indx])
                  != DEBUG_KIND_POINTER))
                  != DEBUG_KIND_POINTER))
            {
            {
              ieee_error (info, start, _("reference parameter is not a pointer"));
              ieee_error (info, start, _("reference parameter is not a pointer"));
              return FALSE;
              return FALSE;
            }
            }
 
 
          target = debug_get_target_type (dhandle, arg_slots[indx]);
          target = debug_get_target_type (dhandle, arg_slots[indx]);
          arg_slots[indx] = debug_make_reference_type (dhandle, target);
          arg_slots[indx] = debug_make_reference_type (dhandle, target);
          if (arg_slots[indx] == DEBUG_TYPE_NULL)
          if (arg_slots[indx] == DEBUG_TYPE_NULL)
            return FALSE;
            return FALSE;
        }
        }
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Read a C++ reference definition.  */
/* Read a C++ reference definition.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_read_reference (struct ieee_info *info, const bfd_byte **pp)
ieee_read_reference (struct ieee_info *info, const bfd_byte **pp)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  bfd_vma flags;
  bfd_vma flags;
  const char *class, *name;
  const char *class, *name;
  unsigned long classlen, namlen;
  unsigned long classlen, namlen;
  debug_type *pslot;
  debug_type *pslot;
  debug_type target;
  debug_type target;
 
 
  start = *pp;
  start = *pp;
 
 
  if (! ieee_require_asn (info, pp, &flags))
  if (! ieee_require_asn (info, pp, &flags))
    return FALSE;
    return FALSE;
 
 
  /* Giving the class name before the member name is in an addendum to
  /* Giving the class name before the member name is in an addendum to
     the spec.  */
     the spec.  */
  if (flags == 3)
  if (flags == 3)
    {
    {
      if (! ieee_require_atn65 (info, pp, &class, &classlen))
      if (! ieee_require_atn65 (info, pp, &class, &classlen))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_require_atn65 (info, pp, &name, &namlen))
  if (! ieee_require_atn65 (info, pp, &name, &namlen))
    return FALSE;
    return FALSE;
 
 
  pslot = NULL;
  pslot = NULL;
  if (flags != 3)
  if (flags != 3)
    {
    {
      int pass;
      int pass;
 
 
      /* We search from the last variable indices to the first in
      /* We search from the last variable indices to the first in
         hopes of finding local variables correctly.  We search the
         hopes of finding local variables correctly.  We search the
         local variables on the first pass, and the global variables
         local variables on the first pass, and the global variables
         on the second.  FIXME: This probably won't work in all cases.
         on the second.  FIXME: This probably won't work in all cases.
         On the other hand, I don't know what will.  */
         On the other hand, I don't know what will.  */
      for (pass = 0; pass < 2; pass++)
      for (pass = 0; pass < 2; pass++)
        {
        {
          struct ieee_vars *vars;
          struct ieee_vars *vars;
          int i;
          int i;
          struct ieee_var *pv = NULL;
          struct ieee_var *pv = NULL;
 
 
          if (pass == 0)
          if (pass == 0)
            vars = &info->vars;
            vars = &info->vars;
          else
          else
            {
            {
              vars = info->global_vars;
              vars = info->global_vars;
              if (vars == NULL)
              if (vars == NULL)
                break;
                break;
            }
            }
 
 
          for (i = (int) vars->alloc - 1; i >= 0; i--)
          for (i = (int) vars->alloc - 1; i >= 0; i--)
            {
            {
              bfd_boolean found;
              bfd_boolean found;
 
 
              pv = vars->vars + i;
              pv = vars->vars + i;
 
 
              if (pv->pslot == NULL
              if (pv->pslot == NULL
                  || pv->namlen != namlen
                  || pv->namlen != namlen
                  || strncmp (pv->name, name, namlen) != 0)
                  || strncmp (pv->name, name, namlen) != 0)
                continue;
                continue;
 
 
              found = FALSE;
              found = FALSE;
              switch (flags)
              switch (flags)
                {
                {
                default:
                default:
                  ieee_error (info, start,
                  ieee_error (info, start,
                              _("unrecognized C++ reference type"));
                              _("unrecognized C++ reference type"));
                  return FALSE;
                  return FALSE;
 
 
                case 0:
                case 0:
                  /* Global variable or function.  */
                  /* Global variable or function.  */
                  if (pv->kind == IEEE_GLOBAL
                  if (pv->kind == IEEE_GLOBAL
                      || pv->kind == IEEE_EXTERNAL
                      || pv->kind == IEEE_EXTERNAL
                      || pv->kind == IEEE_FUNCTION)
                      || pv->kind == IEEE_FUNCTION)
                    found = TRUE;
                    found = TRUE;
                  break;
                  break;
 
 
                case 1:
                case 1:
                  /* Global static variable or function.  */
                  /* Global static variable or function.  */
                  if (pv->kind == IEEE_STATIC
                  if (pv->kind == IEEE_STATIC
                      || pv->kind == IEEE_FUNCTION)
                      || pv->kind == IEEE_FUNCTION)
                    found = TRUE;
                    found = TRUE;
                  break;
                  break;
 
 
                case 2:
                case 2:
                  /* Local variable.  */
                  /* Local variable.  */
                  if (pv->kind == IEEE_LOCAL)
                  if (pv->kind == IEEE_LOCAL)
                    found = TRUE;
                    found = TRUE;
                  break;
                  break;
                }
                }
 
 
              if (found)
              if (found)
                break;
                break;
            }
            }
 
 
          if (i >= 0)
          if (i >= 0)
            {
            {
              pslot = pv->pslot;
              pslot = pv->pslot;
              break;
              break;
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      struct ieee_tag *it;
      struct ieee_tag *it;
 
 
      for (it = info->tags; it != NULL; it = it->next)
      for (it = info->tags; it != NULL; it = it->next)
        {
        {
          if (it->name[0] == class[0]
          if (it->name[0] == class[0]
              && strncmp (it->name, class, classlen) == 0
              && strncmp (it->name, class, classlen) == 0
              && strlen (it->name) == classlen)
              && strlen (it->name) == classlen)
            {
            {
              if (it->fslots != NULL)
              if (it->fslots != NULL)
                {
                {
                  const debug_field *pf;
                  const debug_field *pf;
                  unsigned int findx;
                  unsigned int findx;
 
 
                  pf = debug_get_fields (info->dhandle, it->type);
                  pf = debug_get_fields (info->dhandle, it->type);
                  if (pf == NULL)
                  if (pf == NULL)
                    {
                    {
                      ieee_error (info, start,
                      ieee_error (info, start,
                                  "C++ reference in class with no fields");
                                  "C++ reference in class with no fields");
                      return FALSE;
                      return FALSE;
                    }
                    }
 
 
                  for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
                  for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
                    {
                    {
                      const char *fname;
                      const char *fname;
 
 
                      fname = debug_get_field_name (info->dhandle, *pf);
                      fname = debug_get_field_name (info->dhandle, *pf);
                      if (fname == NULL)
                      if (fname == NULL)
                        return FALSE;
                        return FALSE;
                      if (strncmp (fname, name, namlen) == 0
                      if (strncmp (fname, name, namlen) == 0
                          && strlen (fname) == namlen)
                          && strlen (fname) == namlen)
                        {
                        {
                          pslot = it->fslots + findx;
                          pslot = it->fslots + findx;
                          break;
                          break;
                        }
                        }
                    }
                    }
                }
                }
 
 
              break;
              break;
            }
            }
        }
        }
    }
    }
 
 
  if (pslot == NULL)
  if (pslot == NULL)
    {
    {
      ieee_error (info, start, _("C++ reference not found"));
      ieee_error (info, start, _("C++ reference not found"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  /* We allocated the type of the object as an indirect type pointing
  /* We allocated the type of the object as an indirect type pointing
     to *pslot, which we can now update to be a reference type.  */
     to *pslot, which we can now update to be a reference type.  */
  if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
  if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
    {
    {
      ieee_error (info, start, _("C++ reference is not pointer"));
      ieee_error (info, start, _("C++ reference is not pointer"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  target = debug_get_target_type (info->dhandle, *pslot);
  target = debug_get_target_type (info->dhandle, *pslot);
  *pslot = debug_make_reference_type (info->dhandle, target);
  *pslot = debug_make_reference_type (info->dhandle, target);
  if (*pslot == DEBUG_TYPE_NULL)
  if (*pslot == DEBUG_TYPE_NULL)
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Require an ASN record.  */
/* Require an ASN record.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_require_asn (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
ieee_require_asn (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  ieee_record_enum_type c;
  ieee_record_enum_type c;
  bfd_vma varindx;
  bfd_vma varindx;
 
 
  start = *pp;
  start = *pp;
 
 
  c = (ieee_record_enum_type) **pp;
  c = (ieee_record_enum_type) **pp;
  if (c != ieee_e2_first_byte_enum)
  if (c != ieee_e2_first_byte_enum)
    {
    {
      ieee_error (info, start, _("missing required ASN"));
      ieee_error (info, start, _("missing required ASN"));
      return FALSE;
      return FALSE;
    }
    }
  ++*pp;
  ++*pp;
 
 
  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
  if (c != ieee_asn_record_enum)
  if (c != ieee_asn_record_enum)
    {
    {
      ieee_error (info, start, _("missing required ASN"));
      ieee_error (info, start, _("missing required ASN"));
      return FALSE;
      return FALSE;
    }
    }
  ++*pp;
  ++*pp;
 
 
  /* Just ignore the variable index.  */
  /* Just ignore the variable index.  */
  if (! ieee_read_number (info, pp, &varindx))
  if (! ieee_read_number (info, pp, &varindx))
    return FALSE;
    return FALSE;
 
 
  return ieee_read_expression (info, pp, pv);
  return ieee_read_expression (info, pp, pv);
}
}
 
 
/* Require an ATN65 record.  */
/* Require an ATN65 record.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_require_atn65 (struct ieee_info *info, const bfd_byte **pp,
ieee_require_atn65 (struct ieee_info *info, const bfd_byte **pp,
                    const char **pname, unsigned long *pnamlen)
                    const char **pname, unsigned long *pnamlen)
{
{
  const bfd_byte *start;
  const bfd_byte *start;
  ieee_record_enum_type c;
  ieee_record_enum_type c;
  bfd_vma name_indx, type_indx, atn_code;
  bfd_vma name_indx, type_indx, atn_code;
 
 
  start = *pp;
  start = *pp;
 
 
  c = (ieee_record_enum_type) **pp;
  c = (ieee_record_enum_type) **pp;
  if (c != ieee_at_record_enum)
  if (c != ieee_at_record_enum)
    {
    {
      ieee_error (info, start, _("missing required ATN65"));
      ieee_error (info, start, _("missing required ATN65"));
      return FALSE;
      return FALSE;
    }
    }
  ++*pp;
  ++*pp;
 
 
  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
  if (c != ieee_atn_record_enum)
  if (c != ieee_atn_record_enum)
    {
    {
      ieee_error (info, start, _("missing required ATN65"));
      ieee_error (info, start, _("missing required ATN65"));
      return FALSE;
      return FALSE;
    }
    }
  ++*pp;
  ++*pp;
 
 
  if (! ieee_read_number (info, pp, &name_indx)
  if (! ieee_read_number (info, pp, &name_indx)
      || ! ieee_read_number (info, pp, &type_indx)
      || ! ieee_read_number (info, pp, &type_indx)
      || ! ieee_read_number (info, pp, &atn_code))
      || ! ieee_read_number (info, pp, &atn_code))
    return FALSE;
    return FALSE;
 
 
  /* Just ignore name_indx.  */
  /* Just ignore name_indx.  */
 
 
  if (type_indx != 0 || atn_code != 65)
  if (type_indx != 0 || atn_code != 65)
    {
    {
      ieee_error (info, start, _("bad ATN65 record"));
      ieee_error (info, start, _("bad ATN65 record"));
      return FALSE;
      return FALSE;
    }
    }
 
 
  return ieee_read_id (info, pp, pname, pnamlen);
  return ieee_read_id (info, pp, pname, pnamlen);
}
}


/* Convert a register number in IEEE debugging information into a
/* Convert a register number in IEEE debugging information into a
   generic register number.  */
   generic register number.  */
 
 
static int
static int
ieee_regno_to_genreg (bfd *abfd, int r)
ieee_regno_to_genreg (bfd *abfd, int r)
{
{
  switch (bfd_get_arch (abfd))
  switch (bfd_get_arch (abfd))
    {
    {
    case bfd_arch_m68k:
    case bfd_arch_m68k:
      /* For some reasons stabs adds 2 to the floating point register
      /* For some reasons stabs adds 2 to the floating point register
         numbers.  */
         numbers.  */
      if (r >= 16)
      if (r >= 16)
        r += 2;
        r += 2;
      break;
      break;
 
 
    case bfd_arch_i960:
    case bfd_arch_i960:
      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
         32 to 35 for fp0 to fp3.  */
         32 to 35 for fp0 to fp3.  */
      --r;
      --r;
      break;
      break;
 
 
    default:
    default:
      break;
      break;
    }
    }
 
 
  return r;
  return r;
}
}
 
 
/* Convert a generic register number to an IEEE specific one.  */
/* Convert a generic register number to an IEEE specific one.  */
 
 
static int
static int
ieee_genreg_to_regno (bfd *abfd, int r)
ieee_genreg_to_regno (bfd *abfd, int r)
{
{
  switch (bfd_get_arch (abfd))
  switch (bfd_get_arch (abfd))
    {
    {
    case bfd_arch_m68k:
    case bfd_arch_m68k:
      /* For some reason stabs add 2 to the floating point register
      /* For some reason stabs add 2 to the floating point register
         numbers.  */
         numbers.  */
      if (r >= 18)
      if (r >= 18)
        r -= 2;
        r -= 2;
      break;
      break;
 
 
    case bfd_arch_i960:
    case bfd_arch_i960:
      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
         32 to 35 for fp0 to fp3.  */
         32 to 35 for fp0 to fp3.  */
      ++r;
      ++r;
      break;
      break;
 
 
    default:
    default:
      break;
      break;
    }
    }
 
 
  return r;
  return r;
}
}


/* These routines build IEEE debugging information out of the generic
/* These routines build IEEE debugging information out of the generic
   debugging information.  */
   debugging information.  */
 
 
/* We build the IEEE debugging information byte by byte.  Rather than
/* We build the IEEE debugging information byte by byte.  Rather than
   waste time copying data around, we use a linked list of buffers to
   waste time copying data around, we use a linked list of buffers to
   hold the data.  */
   hold the data.  */
 
 
#define IEEE_BUFSIZE (490)
#define IEEE_BUFSIZE (490)
 
 
struct ieee_buf
struct ieee_buf
{
{
  /* Next buffer.  */
  /* Next buffer.  */
  struct ieee_buf *next;
  struct ieee_buf *next;
  /* Number of data bytes in this buffer.  */
  /* Number of data bytes in this buffer.  */
  unsigned int c;
  unsigned int c;
  /* Bytes.  */
  /* Bytes.  */
  bfd_byte buf[IEEE_BUFSIZE];
  bfd_byte buf[IEEE_BUFSIZE];
};
};
 
 
/* A list of buffers.  */
/* A list of buffers.  */
 
 
struct ieee_buflist
struct ieee_buflist
{
{
  /* Head of list.  */
  /* Head of list.  */
  struct ieee_buf *head;
  struct ieee_buf *head;
  /* Tail--last buffer on list.  */
  /* Tail--last buffer on list.  */
  struct ieee_buf *tail;
  struct ieee_buf *tail;
};
};
 
 
/* In order to generate the BB11 blocks required by the HP emulator,
/* In order to generate the BB11 blocks required by the HP emulator,
   we keep track of ranges of addresses which correspond to a given
   we keep track of ranges of addresses which correspond to a given
   compilation unit.  */
   compilation unit.  */
 
 
struct ieee_range
struct ieee_range
{
{
  /* Next range.  */
  /* Next range.  */
  struct ieee_range *next;
  struct ieee_range *next;
  /* Low address.  */
  /* Low address.  */
  bfd_vma low;
  bfd_vma low;
  /* High address.  */
  /* High address.  */
  bfd_vma high;
  bfd_vma high;
};
};
 
 
/* This structure holds information for a class on the type stack.  */
/* This structure holds information for a class on the type stack.  */
 
 
struct ieee_type_class
struct ieee_type_class
{
{
  /* The name index in the debugging information.  */
  /* The name index in the debugging information.  */
  unsigned int indx;
  unsigned int indx;
  /* The pmisc records for the class.  */
  /* The pmisc records for the class.  */
  struct ieee_buflist pmiscbuf;
  struct ieee_buflist pmiscbuf;
  /* The number of pmisc records.  */
  /* The number of pmisc records.  */
  unsigned int pmisccount;
  unsigned int pmisccount;
  /* The name of the class holding the virtual table, if not this
  /* The name of the class holding the virtual table, if not this
     class.  */
     class.  */
  const char *vclass;
  const char *vclass;
  /* Whether this class holds its own virtual table.  */
  /* Whether this class holds its own virtual table.  */
  bfd_boolean ownvptr;
  bfd_boolean ownvptr;
  /* The largest virtual table offset seen so far.  */
  /* The largest virtual table offset seen so far.  */
  bfd_vma voffset;
  bfd_vma voffset;
  /* The current method.  */
  /* The current method.  */
  const char *method;
  const char *method;
  /* Additional pmisc records used to record fields of reference type.  */
  /* Additional pmisc records used to record fields of reference type.  */
  struct ieee_buflist refs;
  struct ieee_buflist refs;
};
};
 
 
/* This is how we store types for the writing routines.  Most types
/* This is how we store types for the writing routines.  Most types
   are simply represented by a type index.  */
   are simply represented by a type index.  */
 
 
struct ieee_write_type
struct ieee_write_type
{
{
  /* Type index.  */
  /* Type index.  */
  unsigned int indx;
  unsigned int indx;
  /* The size of the type, if known.  */
  /* The size of the type, if known.  */
  unsigned int size;
  unsigned int size;
  /* The name of the type, if any.  */
  /* The name of the type, if any.  */
  const char *name;
  const char *name;
  /* If this is a function or method type, we build the type here, and
  /* If this is a function or method type, we build the type here, and
     only add it to the output buffers if we need it.  */
     only add it to the output buffers if we need it.  */
  struct ieee_buflist fndef;
  struct ieee_buflist fndef;
  /* If this is a struct, this is where the struct definition is
  /* If this is a struct, this is where the struct definition is
     built.  */
     built.  */
  struct ieee_buflist strdef;
  struct ieee_buflist strdef;
  /* If this is a class, this is where the class information is built.  */
  /* If this is a class, this is where the class information is built.  */
  struct ieee_type_class *classdef;
  struct ieee_type_class *classdef;
  /* Whether the type is unsigned.  */
  /* Whether the type is unsigned.  */
  unsigned int unsignedp : 1;
  unsigned int unsignedp : 1;
  /* Whether this is a reference type.  */
  /* Whether this is a reference type.  */
  unsigned int referencep : 1;
  unsigned int referencep : 1;
  /* Whether this is in the local type block.  */
  /* Whether this is in the local type block.  */
  unsigned int localp : 1;
  unsigned int localp : 1;
  /* Whether this is a duplicate struct definition which we are
  /* Whether this is a duplicate struct definition which we are
     ignoring.  */
     ignoring.  */
  unsigned int ignorep : 1;
  unsigned int ignorep : 1;
};
};
 
 
/* This is the type stack used by the debug writing routines.  FIXME:
/* This is the type stack used by the debug writing routines.  FIXME:
   We could generate more efficient output if we remembered when we
   We could generate more efficient output if we remembered when we
   have output a particular type before.  */
   have output a particular type before.  */
 
 
struct ieee_type_stack
struct ieee_type_stack
{
{
  /* Next entry on stack.  */
  /* Next entry on stack.  */
  struct ieee_type_stack *next;
  struct ieee_type_stack *next;
  /* Type information.  */
  /* Type information.  */
  struct ieee_write_type type;
  struct ieee_write_type type;
};
};
 
 
/* This is a list of associations between a name and some types.
/* This is a list of associations between a name and some types.
   These are used for typedefs and tags.  */
   These are used for typedefs and tags.  */
 
 
struct ieee_name_type
struct ieee_name_type
{
{
  /* Next type for this name.  */
  /* Next type for this name.  */
  struct ieee_name_type *next;
  struct ieee_name_type *next;
  /* ID number.  For a typedef, this is the index of the type to which
  /* ID number.  For a typedef, this is the index of the type to which
     this name is typedefed.  */
     this name is typedefed.  */
  unsigned int id;
  unsigned int id;
  /* Type.  */
  /* Type.  */
  struct ieee_write_type type;
  struct ieee_write_type type;
  /* If this is a tag which has not yet been defined, this is the
  /* If this is a tag which has not yet been defined, this is the
     kind.  If the tag has been defined, this is DEBUG_KIND_ILLEGAL.  */
     kind.  If the tag has been defined, this is DEBUG_KIND_ILLEGAL.  */
  enum debug_type_kind kind;
  enum debug_type_kind kind;
};
};
 
 
/* We use a hash table to associate names and types.  */
/* We use a hash table to associate names and types.  */
 
 
struct ieee_name_type_hash_table
struct ieee_name_type_hash_table
{
{
  struct bfd_hash_table root;
  struct bfd_hash_table root;
};
};
 
 
struct ieee_name_type_hash_entry
struct ieee_name_type_hash_entry
{
{
  struct bfd_hash_entry root;
  struct bfd_hash_entry root;
  /* Information for this name.  */
  /* Information for this name.  */
  struct ieee_name_type *types;
  struct ieee_name_type *types;
};
};
 
 
/* This is a list of enums.  */
/* This is a list of enums.  */
 
 
struct ieee_defined_enum
struct ieee_defined_enum
{
{
  /* Next enum.  */
  /* Next enum.  */
  struct ieee_defined_enum *next;
  struct ieee_defined_enum *next;
  /* Type index.  */
  /* Type index.  */
  unsigned int indx;
  unsigned int indx;
  /* Whether this enum has been defined.  */
  /* Whether this enum has been defined.  */
  bfd_boolean defined;
  bfd_boolean defined;
  /* Tag.  */
  /* Tag.  */
  const char *tag;
  const char *tag;
  /* Names.  */
  /* Names.  */
  const char **names;
  const char **names;
  /* Values.  */
  /* Values.  */
  bfd_signed_vma *vals;
  bfd_signed_vma *vals;
};
};
 
 
/* We keep a list of modified versions of types, so that we don't
/* We keep a list of modified versions of types, so that we don't
   output them more than once.  */
   output them more than once.  */
 
 
struct ieee_modified_type
struct ieee_modified_type
{
{
  /* Pointer to this type.  */
  /* Pointer to this type.  */
  unsigned int pointer;
  unsigned int pointer;
  /* Function with unknown arguments returning this type.  */
  /* Function with unknown arguments returning this type.  */
  unsigned int function;
  unsigned int function;
  /* Const version of this type.  */
  /* Const version of this type.  */
  unsigned int const_qualified;
  unsigned int const_qualified;
  /* Volatile version of this type.  */
  /* Volatile version of this type.  */
  unsigned int volatile_qualified;
  unsigned int volatile_qualified;
  /* List of arrays of this type of various bounds.  */
  /* List of arrays of this type of various bounds.  */
  struct ieee_modified_array_type *arrays;
  struct ieee_modified_array_type *arrays;
};
};
 
 
/* A list of arrays bounds.  */
/* A list of arrays bounds.  */
 
 
struct ieee_modified_array_type
struct ieee_modified_array_type
{
{
  /* Next array bounds.  */
  /* Next array bounds.  */
  struct ieee_modified_array_type *next;
  struct ieee_modified_array_type *next;
  /* Type index with these bounds.  */
  /* Type index with these bounds.  */
  unsigned int indx;
  unsigned int indx;
  /* Low bound.  */
  /* Low bound.  */
  bfd_signed_vma low;
  bfd_signed_vma low;
  /* High bound.  */
  /* High bound.  */
  bfd_signed_vma high;
  bfd_signed_vma high;
};
};
 
 
/* This is a list of pending function parameter information.  We don't
/* This is a list of pending function parameter information.  We don't
   output them until we see the first block.  */
   output them until we see the first block.  */
 
 
struct ieee_pending_parm
struct ieee_pending_parm
{
{
  /* Next pending parameter.  */
  /* Next pending parameter.  */
  struct ieee_pending_parm *next;
  struct ieee_pending_parm *next;
  /* Name.  */
  /* Name.  */
  const char *name;
  const char *name;
  /* Type index.  */
  /* Type index.  */
  unsigned int type;
  unsigned int type;
  /* Whether the type is a reference.  */
  /* Whether the type is a reference.  */
  bfd_boolean referencep;
  bfd_boolean referencep;
  /* Kind.  */
  /* Kind.  */
  enum debug_parm_kind kind;
  enum debug_parm_kind kind;
  /* Value.  */
  /* Value.  */
  bfd_vma val;
  bfd_vma val;
};
};
 
 
/* This is the handle passed down by debug_write.  */
/* This is the handle passed down by debug_write.  */
 
 
struct ieee_handle
struct ieee_handle
{
{
  /* BFD we are writing to.  */
  /* BFD we are writing to.  */
  bfd *abfd;
  bfd *abfd;
  /* Whether we got an error in a subroutine called via traverse or
  /* Whether we got an error in a subroutine called via traverse or
     map_over_sections.  */
     map_over_sections.  */
  bfd_boolean error;
  bfd_boolean error;
  /* Current data buffer list.  */
  /* Current data buffer list.  */
  struct ieee_buflist *current;
  struct ieee_buflist *current;
  /* Current data buffer.  */
  /* Current data buffer.  */
  struct ieee_buf *curbuf;
  struct ieee_buf *curbuf;
  /* Filename of current compilation unit.  */
  /* Filename of current compilation unit.  */
  const char *filename;
  const char *filename;
  /* Module name of current compilation unit.  */
  /* Module name of current compilation unit.  */
  const char *modname;
  const char *modname;
  /* List of buffer for global types.  */
  /* List of buffer for global types.  */
  struct ieee_buflist global_types;
  struct ieee_buflist global_types;
  /* List of finished data buffers.  */
  /* List of finished data buffers.  */
  struct ieee_buflist data;
  struct ieee_buflist data;
  /* List of buffers for typedefs in the current compilation unit.  */
  /* List of buffers for typedefs in the current compilation unit.  */
  struct ieee_buflist types;
  struct ieee_buflist types;
  /* List of buffers for variables and functions in the current
  /* List of buffers for variables and functions in the current
     compilation unit.  */
     compilation unit.  */
  struct ieee_buflist vars;
  struct ieee_buflist vars;
  /* List of buffers for C++ class definitions in the current
  /* List of buffers for C++ class definitions in the current
     compilation unit.  */
     compilation unit.  */
  struct ieee_buflist cxx;
  struct ieee_buflist cxx;
  /* List of buffers for line numbers in the current compilation unit.  */
  /* List of buffers for line numbers in the current compilation unit.  */
  struct ieee_buflist linenos;
  struct ieee_buflist linenos;
  /* Ranges for the current compilation unit.  */
  /* Ranges for the current compilation unit.  */
  struct ieee_range *ranges;
  struct ieee_range *ranges;
  /* Ranges for all debugging information.  */
  /* Ranges for all debugging information.  */
  struct ieee_range *global_ranges;
  struct ieee_range *global_ranges;
  /* Nested pending ranges.  */
  /* Nested pending ranges.  */
  struct ieee_range *pending_ranges;
  struct ieee_range *pending_ranges;
  /* Type stack.  */
  /* Type stack.  */
  struct ieee_type_stack *type_stack;
  struct ieee_type_stack *type_stack;
  /* Next unallocated type index.  */
  /* Next unallocated type index.  */
  unsigned int type_indx;
  unsigned int type_indx;
  /* Next unallocated name index.  */
  /* Next unallocated name index.  */
  unsigned int name_indx;
  unsigned int name_indx;
  /* Typedefs.  */
  /* Typedefs.  */
  struct ieee_name_type_hash_table typedefs;
  struct ieee_name_type_hash_table typedefs;
  /* Tags.  */
  /* Tags.  */
  struct ieee_name_type_hash_table tags;
  struct ieee_name_type_hash_table tags;
  /* Enums.  */
  /* Enums.  */
  struct ieee_defined_enum *enums;
  struct ieee_defined_enum *enums;
  /* Modified versions of types.  */
  /* Modified versions of types.  */
  struct ieee_modified_type *modified;
  struct ieee_modified_type *modified;
  /* Number of entries allocated in modified.  */
  /* Number of entries allocated in modified.  */
  unsigned int modified_alloc;
  unsigned int modified_alloc;
  /* 4 byte complex type.  */
  /* 4 byte complex type.  */
  unsigned int complex_float_index;
  unsigned int complex_float_index;
  /* 8 byte complex type.  */
  /* 8 byte complex type.  */
  unsigned int complex_double_index;
  unsigned int complex_double_index;
  /* The depth of block nesting.  This is 0 outside a function, and 1
  /* The depth of block nesting.  This is 0 outside a function, and 1
     just after start_function is called.  */
     just after start_function is called.  */
  unsigned int block_depth;
  unsigned int block_depth;
  /* The name of the current function.  */
  /* The name of the current function.  */
  const char *fnname;
  const char *fnname;
  /* List of buffers for the type of the function we are currently
  /* List of buffers for the type of the function we are currently
     writing out.  */
     writing out.  */
  struct ieee_buflist fntype;
  struct ieee_buflist fntype;
  /* List of buffers for the parameters of the function we are
  /* List of buffers for the parameters of the function we are
     currently writing out.  */
     currently writing out.  */
  struct ieee_buflist fnargs;
  struct ieee_buflist fnargs;
  /* Number of arguments written to fnargs.  */
  /* Number of arguments written to fnargs.  */
  unsigned int fnargcount;
  unsigned int fnargcount;
  /* Pending function parameters.  */
  /* Pending function parameters.  */
  struct ieee_pending_parm *pending_parms;
  struct ieee_pending_parm *pending_parms;
  /* Current line number filename.  */
  /* Current line number filename.  */
  const char *lineno_filename;
  const char *lineno_filename;
  /* Line number name index.  */
  /* Line number name index.  */
  unsigned int lineno_name_indx;
  unsigned int lineno_name_indx;
  /* Filename of pending line number.  */
  /* Filename of pending line number.  */
  const char *pending_lineno_filename;
  const char *pending_lineno_filename;
  /* Pending line number.  */
  /* Pending line number.  */
  unsigned long pending_lineno;
  unsigned long pending_lineno;
  /* Address of pending line number.  */
  /* Address of pending line number.  */
  bfd_vma pending_lineno_addr;
  bfd_vma pending_lineno_addr;
  /* Highest address seen at end of procedure.  */
  /* Highest address seen at end of procedure.  */
  bfd_vma highaddr;
  bfd_vma highaddr;
};
};
 
 
static bfd_boolean ieee_init_buffer
static bfd_boolean ieee_init_buffer
  (struct ieee_handle *, struct ieee_buflist *);
  (struct ieee_handle *, struct ieee_buflist *);
static bfd_boolean ieee_change_buffer
static bfd_boolean ieee_change_buffer
  (struct ieee_handle *, struct ieee_buflist *);
  (struct ieee_handle *, struct ieee_buflist *);
static bfd_boolean ieee_append_buffer
static bfd_boolean ieee_append_buffer
  (struct ieee_handle *, struct ieee_buflist *, struct ieee_buflist *);
  (struct ieee_handle *, struct ieee_buflist *, struct ieee_buflist *);
static bfd_boolean ieee_real_write_byte (struct ieee_handle *, int);
static bfd_boolean ieee_real_write_byte (struct ieee_handle *, int);
static bfd_boolean ieee_write_2bytes (struct ieee_handle *, int);
static bfd_boolean ieee_write_2bytes (struct ieee_handle *, int);
static bfd_boolean ieee_write_number (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_write_number (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_write_id (struct ieee_handle *, const char *);
static bfd_boolean ieee_write_id (struct ieee_handle *, const char *);
static bfd_boolean ieee_write_asn
static bfd_boolean ieee_write_asn
  (struct ieee_handle *, unsigned int, bfd_vma);
  (struct ieee_handle *, unsigned int, bfd_vma);
static bfd_boolean ieee_write_atn65
static bfd_boolean ieee_write_atn65
  (struct ieee_handle *, unsigned int, const char *);
  (struct ieee_handle *, unsigned int, const char *);
static bfd_boolean ieee_push_type
static bfd_boolean ieee_push_type
  (struct ieee_handle *, unsigned int, unsigned int, bfd_boolean,
  (struct ieee_handle *, unsigned int, unsigned int, bfd_boolean,
   bfd_boolean);
   bfd_boolean);
static unsigned int ieee_pop_type (struct ieee_handle *);
static unsigned int ieee_pop_type (struct ieee_handle *);
static void ieee_pop_unused_type (struct ieee_handle *);
static void ieee_pop_unused_type (struct ieee_handle *);
static unsigned int ieee_pop_type_used (struct ieee_handle *, bfd_boolean);
static unsigned int ieee_pop_type_used (struct ieee_handle *, bfd_boolean);
static bfd_boolean ieee_add_range
static bfd_boolean ieee_add_range
  (struct ieee_handle *, bfd_boolean, bfd_vma, bfd_vma);
  (struct ieee_handle *, bfd_boolean, bfd_vma, bfd_vma);
static bfd_boolean ieee_start_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_start_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_end_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_end_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_define_type
static bfd_boolean ieee_define_type
  (struct ieee_handle *, unsigned int, bfd_boolean, bfd_boolean);
  (struct ieee_handle *, unsigned int, bfd_boolean, bfd_boolean);
static bfd_boolean ieee_define_named_type
static bfd_boolean ieee_define_named_type
  (struct ieee_handle *, const char *, unsigned int, unsigned int,
  (struct ieee_handle *, const char *, unsigned int, unsigned int,
   bfd_boolean, bfd_boolean, struct ieee_buflist *);
   bfd_boolean, bfd_boolean, struct ieee_buflist *);
static struct ieee_modified_type *ieee_get_modified_info
static struct ieee_modified_type *ieee_get_modified_info
  (struct ieee_handle *, unsigned int);
  (struct ieee_handle *, unsigned int);
static struct bfd_hash_entry *ieee_name_type_newfunc
static struct bfd_hash_entry *ieee_name_type_newfunc
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
static bfd_boolean ieee_write_undefined_tag
static bfd_boolean ieee_write_undefined_tag
  (struct ieee_name_type_hash_entry *, void *);
  (struct ieee_name_type_hash_entry *, void *);
static bfd_boolean ieee_finish_compilation_unit (struct ieee_handle *);
static bfd_boolean ieee_finish_compilation_unit (struct ieee_handle *);
static void ieee_add_bb11_blocks (bfd *, asection *, void *);
static void ieee_add_bb11_blocks (bfd *, asection *, void *);
static bfd_boolean ieee_add_bb11
static bfd_boolean ieee_add_bb11
  (struct ieee_handle *, asection *, bfd_vma, bfd_vma);
  (struct ieee_handle *, asection *, bfd_vma, bfd_vma);
static bfd_boolean ieee_output_pending_parms (struct ieee_handle *);
static bfd_boolean ieee_output_pending_parms (struct ieee_handle *);
static unsigned int ieee_vis_to_flags (enum debug_visibility);
static unsigned int ieee_vis_to_flags (enum debug_visibility);
static bfd_boolean ieee_class_method_var
static bfd_boolean ieee_class_method_var
  (struct ieee_handle *, const char *, enum debug_visibility, bfd_boolean,
  (struct ieee_handle *, const char *, enum debug_visibility, bfd_boolean,
   bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
   bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
 
 
static bfd_boolean ieee_start_compilation_unit (void *, const char *);
static bfd_boolean ieee_start_compilation_unit (void *, const char *);
static bfd_boolean ieee_start_source (void *, const char *);
static bfd_boolean ieee_start_source (void *, const char *);
static bfd_boolean ieee_empty_type (void *);
static bfd_boolean ieee_empty_type (void *);
static bfd_boolean ieee_void_type (void *);
static bfd_boolean ieee_void_type (void *);
static bfd_boolean ieee_int_type (void *, unsigned int, bfd_boolean);
static bfd_boolean ieee_int_type (void *, unsigned int, bfd_boolean);
static bfd_boolean ieee_float_type (void *, unsigned int);
static bfd_boolean ieee_float_type (void *, unsigned int);
static bfd_boolean ieee_complex_type (void *, unsigned int);
static bfd_boolean ieee_complex_type (void *, unsigned int);
static bfd_boolean ieee_bool_type (void *, unsigned int);
static bfd_boolean ieee_bool_type (void *, unsigned int);
static bfd_boolean ieee_enum_type
static bfd_boolean ieee_enum_type
  (void *, const char *, const char **, bfd_signed_vma *);
  (void *, const char *, const char **, bfd_signed_vma *);
static bfd_boolean ieee_pointer_type (void *);
static bfd_boolean ieee_pointer_type (void *);
static bfd_boolean ieee_function_type (void *, int, bfd_boolean);
static bfd_boolean ieee_function_type (void *, int, bfd_boolean);
static bfd_boolean ieee_reference_type (void *);
static bfd_boolean ieee_reference_type (void *);
static bfd_boolean ieee_range_type (void *, bfd_signed_vma, bfd_signed_vma);
static bfd_boolean ieee_range_type (void *, bfd_signed_vma, bfd_signed_vma);
static bfd_boolean ieee_array_type
static bfd_boolean ieee_array_type
  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
  (void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
static bfd_boolean ieee_set_type (void *, bfd_boolean);
static bfd_boolean ieee_set_type (void *, bfd_boolean);
static bfd_boolean ieee_offset_type (void *);
static bfd_boolean ieee_offset_type (void *);
static bfd_boolean ieee_method_type (void *, bfd_boolean, int, bfd_boolean);
static bfd_boolean ieee_method_type (void *, bfd_boolean, int, bfd_boolean);
static bfd_boolean ieee_const_type (void *);
static bfd_boolean ieee_const_type (void *);
static bfd_boolean ieee_volatile_type (void *);
static bfd_boolean ieee_volatile_type (void *);
static bfd_boolean ieee_start_struct_type
static bfd_boolean ieee_start_struct_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
  (void *, const char *, unsigned int, bfd_boolean, unsigned int);
static bfd_boolean ieee_struct_field
static bfd_boolean ieee_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 ieee_end_struct_type (void *);
static bfd_boolean ieee_end_struct_type (void *);
static bfd_boolean ieee_start_class_type
static bfd_boolean ieee_start_class_type
  (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
  (void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
   bfd_boolean);
   bfd_boolean);
static bfd_boolean ieee_class_static_member
static bfd_boolean ieee_class_static_member
  (void *, const char *, const char *, enum debug_visibility);
  (void *, const char *, const char *, enum debug_visibility);
static bfd_boolean ieee_class_baseclass
static bfd_boolean ieee_class_baseclass
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
  (void *, bfd_vma, bfd_boolean, enum debug_visibility);
static bfd_boolean ieee_class_start_method (void *, const char *);
static bfd_boolean ieee_class_start_method (void *, const char *);
static bfd_boolean ieee_class_method_variant
static bfd_boolean ieee_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 ieee_class_static_method_variant
static bfd_boolean ieee_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 ieee_class_end_method (void *);
static bfd_boolean ieee_class_end_method (void *);
static bfd_boolean ieee_end_class_type (void *);
static bfd_boolean ieee_end_class_type (void *);
static bfd_boolean ieee_typedef_type (void *, const char *);
static bfd_boolean ieee_typedef_type (void *, const char *);
static bfd_boolean ieee_tag_type
static bfd_boolean ieee_tag_type
  (void *, const char *, unsigned int, enum debug_type_kind);
  (void *, const char *, unsigned int, enum debug_type_kind);
static bfd_boolean ieee_typdef (void *, const char *);
static bfd_boolean ieee_typdef (void *, const char *);
static bfd_boolean ieee_tag (void *, const char *);
static bfd_boolean ieee_tag (void *, const char *);
static bfd_boolean ieee_int_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_int_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_float_constant (void *, const char *, double);
static bfd_boolean ieee_float_constant (void *, const char *, double);
static bfd_boolean ieee_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_variable
static bfd_boolean ieee_variable
  (void *, const char *, enum debug_var_kind, bfd_vma);
  (void *, const char *, enum debug_var_kind, bfd_vma);
static bfd_boolean ieee_start_function (void *, const char *, bfd_boolean);
static bfd_boolean ieee_start_function (void *, const char *, bfd_boolean);
static bfd_boolean ieee_function_parameter
static bfd_boolean ieee_function_parameter
  (void *, const char *, enum debug_parm_kind, bfd_vma);
  (void *, const char *, enum debug_parm_kind, bfd_vma);
static bfd_boolean ieee_start_block (void *, bfd_vma);
static bfd_boolean ieee_start_block (void *, bfd_vma);
static bfd_boolean ieee_end_block (void *, bfd_vma);
static bfd_boolean ieee_end_block (void *, bfd_vma);
static bfd_boolean ieee_end_function (void *);
static bfd_boolean ieee_end_function (void *);
static bfd_boolean ieee_lineno (void *, const char *, unsigned long, bfd_vma);
static bfd_boolean ieee_lineno (void *, const char *, unsigned long, bfd_vma);
 
 
static const struct debug_write_fns ieee_fns =
static const struct debug_write_fns ieee_fns =
{
{
  ieee_start_compilation_unit,
  ieee_start_compilation_unit,
  ieee_start_source,
  ieee_start_source,
  ieee_empty_type,
  ieee_empty_type,
  ieee_void_type,
  ieee_void_type,
  ieee_int_type,
  ieee_int_type,
  ieee_float_type,
  ieee_float_type,
  ieee_complex_type,
  ieee_complex_type,
  ieee_bool_type,
  ieee_bool_type,
  ieee_enum_type,
  ieee_enum_type,
  ieee_pointer_type,
  ieee_pointer_type,
  ieee_function_type,
  ieee_function_type,
  ieee_reference_type,
  ieee_reference_type,
  ieee_range_type,
  ieee_range_type,
  ieee_array_type,
  ieee_array_type,
  ieee_set_type,
  ieee_set_type,
  ieee_offset_type,
  ieee_offset_type,
  ieee_method_type,
  ieee_method_type,
  ieee_const_type,
  ieee_const_type,
  ieee_volatile_type,
  ieee_volatile_type,
  ieee_start_struct_type,
  ieee_start_struct_type,
  ieee_struct_field,
  ieee_struct_field,
  ieee_end_struct_type,
  ieee_end_struct_type,
  ieee_start_class_type,
  ieee_start_class_type,
  ieee_class_static_member,
  ieee_class_static_member,
  ieee_class_baseclass,
  ieee_class_baseclass,
  ieee_class_start_method,
  ieee_class_start_method,
  ieee_class_method_variant,
  ieee_class_method_variant,
  ieee_class_static_method_variant,
  ieee_class_static_method_variant,
  ieee_class_end_method,
  ieee_class_end_method,
  ieee_end_class_type,
  ieee_end_class_type,
  ieee_typedef_type,
  ieee_typedef_type,
  ieee_tag_type,
  ieee_tag_type,
  ieee_typdef,
  ieee_typdef,
  ieee_tag,
  ieee_tag,
  ieee_int_constant,
  ieee_int_constant,
  ieee_float_constant,
  ieee_float_constant,
  ieee_typed_constant,
  ieee_typed_constant,
  ieee_variable,
  ieee_variable,
  ieee_start_function,
  ieee_start_function,
  ieee_function_parameter,
  ieee_function_parameter,
  ieee_start_block,
  ieee_start_block,
  ieee_end_block,
  ieee_end_block,
  ieee_end_function,
  ieee_end_function,
  ieee_lineno
  ieee_lineno
};
};
 
 
/* Initialize a buffer to be empty.  */
/* Initialize a buffer to be empty.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_init_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
ieee_init_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
                  struct ieee_buflist *buflist)
                  struct ieee_buflist *buflist)
{
{
  buflist->head = NULL;
  buflist->head = NULL;
  buflist->tail = NULL;
  buflist->tail = NULL;
  return TRUE;
  return TRUE;
}
}
 
 
/* See whether a buffer list has any data.  */
/* See whether a buffer list has any data.  */
 
 
#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
 
 
/* Change the current buffer to a specified buffer chain.  */
/* Change the current buffer to a specified buffer chain.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_change_buffer (struct ieee_handle *info, struct ieee_buflist *buflist)
ieee_change_buffer (struct ieee_handle *info, struct ieee_buflist *buflist)
{
{
  if (buflist->head == NULL)
  if (buflist->head == NULL)
    {
    {
      struct ieee_buf *buf;
      struct ieee_buf *buf;
 
 
      buf = (struct ieee_buf *) xmalloc (sizeof *buf);
      buf = (struct ieee_buf *) xmalloc (sizeof *buf);
      buf->next = NULL;
      buf->next = NULL;
      buf->c = 0;
      buf->c = 0;
      buflist->head = buf;
      buflist->head = buf;
      buflist->tail = buf;
      buflist->tail = buf;
    }
    }
 
 
  info->current = buflist;
  info->current = buflist;
  info->curbuf = buflist->tail;
  info->curbuf = buflist->tail;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Append a buffer chain.  */
/* Append a buffer chain.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_append_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
ieee_append_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
                    struct ieee_buflist *mainbuf,
                    struct ieee_buflist *mainbuf,
                    struct ieee_buflist *newbuf)
                    struct ieee_buflist *newbuf)
{
{
  if (newbuf->head != NULL)
  if (newbuf->head != NULL)
    {
    {
      if (mainbuf->head == NULL)
      if (mainbuf->head == NULL)
        mainbuf->head = newbuf->head;
        mainbuf->head = newbuf->head;
      else
      else
        mainbuf->tail->next = newbuf->head;
        mainbuf->tail->next = newbuf->head;
      mainbuf->tail = newbuf->tail;
      mainbuf->tail = newbuf->tail;
    }
    }
  return TRUE;
  return TRUE;
}
}
 
 
/* Write a byte into the buffer.  We use a macro for speed and a
/* Write a byte into the buffer.  We use a macro for speed and a
   function for the complex cases.  */
   function for the complex cases.  */
 
 
#define ieee_write_byte(info, b)                                \
#define ieee_write_byte(info, b)                                \
  ((info)->curbuf->c < IEEE_BUFSIZE                             \
  ((info)->curbuf->c < IEEE_BUFSIZE                             \
   ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), TRUE)     \
   ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), TRUE)     \
   : ieee_real_write_byte ((info), (b)))
   : ieee_real_write_byte ((info), (b)))
 
 
static bfd_boolean
static bfd_boolean
ieee_real_write_byte (struct ieee_handle *info, int b)
ieee_real_write_byte (struct ieee_handle *info, int b)
{
{
  if (info->curbuf->c >= IEEE_BUFSIZE)
  if (info->curbuf->c >= IEEE_BUFSIZE)
    {
    {
      struct ieee_buf *n;
      struct ieee_buf *n;
 
 
      n = (struct ieee_buf *) xmalloc (sizeof *n);
      n = (struct ieee_buf *) xmalloc (sizeof *n);
      n->next = NULL;
      n->next = NULL;
      n->c = 0;
      n->c = 0;
      if (info->current->head == NULL)
      if (info->current->head == NULL)
        info->current->head = n;
        info->current->head = n;
      else
      else
        info->current->tail->next = n;
        info->current->tail->next = n;
      info->current->tail = n;
      info->current->tail = n;
      info->curbuf = n;
      info->curbuf = n;
    }
    }
 
 
  info->curbuf->buf[info->curbuf->c] = b;
  info->curbuf->buf[info->curbuf->c] = b;
  ++info->curbuf->c;
  ++info->curbuf->c;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out two bytes.  */
/* Write out two bytes.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_2bytes (struct ieee_handle *info, int i)
ieee_write_2bytes (struct ieee_handle *info, int i)
{
{
  return (ieee_write_byte (info, i >> 8)
  return (ieee_write_byte (info, i >> 8)
          && ieee_write_byte (info, i & 0xff));
          && ieee_write_byte (info, i & 0xff));
}
}
 
 
/* Write out an integer.  */
/* Write out an integer.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_number (struct ieee_handle *info, bfd_vma v)
ieee_write_number (struct ieee_handle *info, bfd_vma v)
{
{
  bfd_vma t;
  bfd_vma t;
  bfd_byte ab[20];
  bfd_byte ab[20];
  bfd_byte *p;
  bfd_byte *p;
  unsigned int c;
  unsigned int c;
 
 
  if (v <= (bfd_vma) ieee_number_end_enum)
  if (v <= (bfd_vma) ieee_number_end_enum)
    return ieee_write_byte (info, (int) v);
    return ieee_write_byte (info, (int) v);
 
 
  t = v;
  t = v;
  p = ab + sizeof ab;
  p = ab + sizeof ab;
  while (t != 0)
  while (t != 0)
    {
    {
      *--p = t & 0xff;
      *--p = t & 0xff;
      t >>= 8;
      t >>= 8;
    }
    }
  c = (ab + 20) - p;
  c = (ab + 20) - p;
 
 
  if (c > (unsigned int) (ieee_number_repeat_end_enum
  if (c > (unsigned int) (ieee_number_repeat_end_enum
                          - ieee_number_repeat_start_enum))
                          - ieee_number_repeat_start_enum))
    {
    {
      fprintf (stderr, _("IEEE numeric overflow: 0x"));
      fprintf (stderr, _("IEEE numeric overflow: 0x"));
      fprintf_vma (stderr, v);
      fprintf_vma (stderr, v);
      fprintf (stderr, "\n");
      fprintf (stderr, "\n");
      return FALSE;
      return FALSE;
    }
    }
 
 
  if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
  if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
    return FALSE;
    return FALSE;
  for (; c > 0; --c, ++p)
  for (; c > 0; --c, ++p)
    {
    {
      if (! ieee_write_byte (info, *p))
      if (! ieee_write_byte (info, *p))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out a string.  */
/* Write out a string.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_id (struct ieee_handle *info, const char *s)
ieee_write_id (struct ieee_handle *info, const char *s)
{
{
  unsigned int len;
  unsigned int len;
 
 
  len = strlen (s);
  len = strlen (s);
  if (len <= 0x7f)
  if (len <= 0x7f)
    {
    {
      if (! ieee_write_byte (info, len))
      if (! ieee_write_byte (info, len))
        return FALSE;
        return FALSE;
    }
    }
  else if (len <= 0xff)
  else if (len <= 0xff)
    {
    {
      if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
      if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
          || ! ieee_write_byte (info, len))
          || ! ieee_write_byte (info, len))
        return FALSE;
        return FALSE;
    }
    }
  else if (len <= 0xffff)
  else if (len <= 0xffff)
    {
    {
      if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
      if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
          || ! ieee_write_2bytes (info, len))
          || ! ieee_write_2bytes (info, len))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      fprintf (stderr, _("IEEE string length overflow: %u\n"), len);
      fprintf (stderr, _("IEEE string length overflow: %u\n"), len);
      return FALSE;
      return FALSE;
    }
    }
 
 
  for (; *s != '\0'; s++)
  for (; *s != '\0'; s++)
    if (! ieee_write_byte (info, *s))
    if (! ieee_write_byte (info, *s))
      return FALSE;
      return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out an ASN record.  */
/* Write out an ASN record.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_asn (struct ieee_handle *info, unsigned int indx, bfd_vma val)
ieee_write_asn (struct ieee_handle *info, unsigned int indx, bfd_vma val)
{
{
  return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
  return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, val));
          && ieee_write_number (info, val));
}
}
 
 
/* Write out an ATN65 record.  */
/* Write out an ATN65 record.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_atn65 (struct ieee_handle *info, unsigned int indx, const char *s)
ieee_write_atn65 (struct ieee_handle *info, unsigned int indx, const char *s)
{
{
  return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
  return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, 0)
          && ieee_write_number (info, 0)
          && ieee_write_number (info, 65)
          && ieee_write_number (info, 65)
          && ieee_write_id (info, s));
          && ieee_write_id (info, s));
}
}
 
 
/* Push a type index onto the type stack.  */
/* Push a type index onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_push_type (struct ieee_handle *info, unsigned int indx,
ieee_push_type (struct ieee_handle *info, unsigned int indx,
                unsigned int size, bfd_boolean unsignedp, bfd_boolean localp)
                unsigned int size, bfd_boolean unsignedp, bfd_boolean localp)
{
{
  struct ieee_type_stack *ts;
  struct ieee_type_stack *ts;
 
 
  ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
  ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
  memset (ts, 0, sizeof *ts);
  memset (ts, 0, sizeof *ts);
 
 
  ts->type.indx = indx;
  ts->type.indx = indx;
  ts->type.size = size;
  ts->type.size = size;
  ts->type.unsignedp = unsignedp;
  ts->type.unsignedp = unsignedp;
  ts->type.localp = localp;
  ts->type.localp = localp;
 
 
  ts->next = info->type_stack;
  ts->next = info->type_stack;
  info->type_stack = ts;
  info->type_stack = ts;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Pop a type index off the type stack.  */
/* Pop a type index off the type stack.  */
 
 
static unsigned int
static unsigned int
ieee_pop_type (struct ieee_handle *info)
ieee_pop_type (struct ieee_handle *info)
{
{
  return ieee_pop_type_used (info, TRUE);
  return ieee_pop_type_used (info, TRUE);
}
}
 
 
/* Pop an unused type index off the type stack.  */
/* Pop an unused type index off the type stack.  */
 
 
static void
static void
ieee_pop_unused_type (struct ieee_handle *info)
ieee_pop_unused_type (struct ieee_handle *info)
{
{
  (void) ieee_pop_type_used (info, FALSE);
  (void) ieee_pop_type_used (info, FALSE);
}
}
 
 
/* Pop a used or unused type index off the type stack.  */
/* Pop a used or unused type index off the type stack.  */
 
 
static unsigned int
static unsigned int
ieee_pop_type_used (struct ieee_handle *info, bfd_boolean used)
ieee_pop_type_used (struct ieee_handle *info, bfd_boolean used)
{
{
  struct ieee_type_stack *ts;
  struct ieee_type_stack *ts;
  unsigned int ret;
  unsigned int ret;
 
 
  ts = info->type_stack;
  ts = info->type_stack;
  assert (ts != NULL);
  assert (ts != NULL);
 
 
  /* If this is a function type, and we need it, we need to append the
  /* If this is a function type, and we need it, we need to append the
     actual definition to the typedef block now.  */
     actual definition to the typedef block now.  */
  if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
  if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
    {
    {
      struct ieee_buflist *buflist;
      struct ieee_buflist *buflist;
 
 
      if (ts->type.localp)
      if (ts->type.localp)
        {
        {
          /* Make sure we have started the types block.  */
          /* Make sure we have started the types block.  */
          if (ieee_buffer_emptyp (&info->types))
          if (ieee_buffer_emptyp (&info->types))
            {
            {
              if (! ieee_change_buffer (info, &info->types)
              if (! ieee_change_buffer (info, &info->types)
                  || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
                  || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
                  || ! ieee_write_byte (info, 1)
                  || ! ieee_write_byte (info, 1)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_id (info, info->modname))
                  || ! ieee_write_id (info, info->modname))
                return FALSE;
                return FALSE;
            }
            }
          buflist = &info->types;
          buflist = &info->types;
        }
        }
      else
      else
        {
        {
          /* Make sure we started the global type block.  */
          /* Make sure we started the global type block.  */
          if (ieee_buffer_emptyp (&info->global_types))
          if (ieee_buffer_emptyp (&info->global_types))
            {
            {
              if (! ieee_change_buffer (info, &info->global_types)
              if (! ieee_change_buffer (info, &info->global_types)
                  || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
                  || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
                  || ! ieee_write_byte (info, 2)
                  || ! ieee_write_byte (info, 2)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_id (info, ""))
                  || ! ieee_write_id (info, ""))
                return FALSE;
                return FALSE;
            }
            }
          buflist = &info->global_types;
          buflist = &info->global_types;
        }
        }
 
 
      if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
      if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
        return FALSE;
        return FALSE;
    }
    }
 
 
  ret = ts->type.indx;
  ret = ts->type.indx;
  info->type_stack = ts->next;
  info->type_stack = ts->next;
  free (ts);
  free (ts);
  return ret;
  return ret;
}
}
 
 
/* Add a range of bytes included in the current compilation unit.  */
/* Add a range of bytes included in the current compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_add_range (struct ieee_handle *info, bfd_boolean global, bfd_vma low,
ieee_add_range (struct ieee_handle *info, bfd_boolean global, bfd_vma low,
                bfd_vma high)
                bfd_vma high)
{
{
  struct ieee_range **plist, *r, **pr;
  struct ieee_range **plist, *r, **pr;
 
 
  if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
  if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
    return TRUE;
    return TRUE;
 
 
  if (global)
  if (global)
    plist = &info->global_ranges;
    plist = &info->global_ranges;
  else
  else
    plist = &info->ranges;
    plist = &info->ranges;
 
 
  for (r = *plist; r != NULL; r = r->next)
  for (r = *plist; r != NULL; r = r->next)
    {
    {
      if (high >= r->low && low <= r->high)
      if (high >= r->low && low <= r->high)
        {
        {
          /* The new range overlaps r.  */
          /* The new range overlaps r.  */
          if (low < r->low)
          if (low < r->low)
            r->low = low;
            r->low = low;
          if (high > r->high)
          if (high > r->high)
            r->high = high;
            r->high = high;
          pr = &r->next;
          pr = &r->next;
          while (*pr != NULL && (*pr)->low <= r->high)
          while (*pr != NULL && (*pr)->low <= r->high)
            {
            {
              struct ieee_range *n;
              struct ieee_range *n;
 
 
              if ((*pr)->high > r->high)
              if ((*pr)->high > r->high)
                r->high = (*pr)->high;
                r->high = (*pr)->high;
              n = (*pr)->next;
              n = (*pr)->next;
              free (*pr);
              free (*pr);
              *pr = n;
              *pr = n;
            }
            }
          return TRUE;
          return TRUE;
        }
        }
    }
    }
 
 
  r = (struct ieee_range *) xmalloc (sizeof *r);
  r = (struct ieee_range *) xmalloc (sizeof *r);
  memset (r, 0, sizeof *r);
  memset (r, 0, sizeof *r);
 
 
  r->low = low;
  r->low = low;
  r->high = high;
  r->high = high;
 
 
  /* Store the ranges sorted by address.  */
  /* Store the ranges sorted by address.  */
  for (pr = plist; *pr != NULL; pr = &(*pr)->next)
  for (pr = plist; *pr != NULL; pr = &(*pr)->next)
    if ((*pr)->low > high)
    if ((*pr)->low > high)
      break;
      break;
  r->next = *pr;
  r->next = *pr;
  *pr = r;
  *pr = r;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a new range for which we only have the low address.  */
/* Start a new range for which we only have the low address.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_range (struct ieee_handle *info, bfd_vma low)
ieee_start_range (struct ieee_handle *info, bfd_vma low)
{
{
  struct ieee_range *r;
  struct ieee_range *r;
 
 
  r = (struct ieee_range *) xmalloc (sizeof *r);
  r = (struct ieee_range *) xmalloc (sizeof *r);
  memset (r, 0, sizeof *r);
  memset (r, 0, sizeof *r);
  r->low = low;
  r->low = low;
  r->next = info->pending_ranges;
  r->next = info->pending_ranges;
  info->pending_ranges = r;
  info->pending_ranges = r;
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish a range started by ieee_start_range.  */
/* Finish a range started by ieee_start_range.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_end_range (struct ieee_handle *info, bfd_vma high)
ieee_end_range (struct ieee_handle *info, bfd_vma high)
{
{
  struct ieee_range *r;
  struct ieee_range *r;
  bfd_vma low;
  bfd_vma low;
 
 
  assert (info->pending_ranges != NULL);
  assert (info->pending_ranges != NULL);
  r = info->pending_ranges;
  r = info->pending_ranges;
  low = r->low;
  low = r->low;
  info->pending_ranges = r->next;
  info->pending_ranges = r->next;
  free (r);
  free (r);
  return ieee_add_range (info, FALSE, low, high);
  return ieee_add_range (info, FALSE, low, high);
}
}
 
 
/* Start defining a type.  */
/* Start defining a type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_define_type (struct ieee_handle *info, unsigned int size,
ieee_define_type (struct ieee_handle *info, unsigned int size,
                  bfd_boolean unsignedp, bfd_boolean localp)
                  bfd_boolean unsignedp, bfd_boolean localp)
{
{
  return ieee_define_named_type (info, (const char *) NULL,
  return ieee_define_named_type (info, (const char *) NULL,
                                 (unsigned int) -1, size, unsignedp,
                                 (unsigned int) -1, size, unsignedp,
                                 localp, (struct ieee_buflist *) NULL);
                                 localp, (struct ieee_buflist *) NULL);
}
}
 
 
/* Start defining a named type.  */
/* Start defining a named type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_define_named_type (struct ieee_handle *info, const char *name,
ieee_define_named_type (struct ieee_handle *info, const char *name,
                        unsigned int indx, unsigned int size,
                        unsigned int indx, unsigned int size,
                        bfd_boolean unsignedp, bfd_boolean localp,
                        bfd_boolean unsignedp, bfd_boolean localp,
                        struct ieee_buflist *buflist)
                        struct ieee_buflist *buflist)
{
{
  unsigned int type_indx;
  unsigned int type_indx;
  unsigned int name_indx;
  unsigned int name_indx;
 
 
  if (indx != (unsigned int) -1)
  if (indx != (unsigned int) -1)
    type_indx = indx;
    type_indx = indx;
  else
  else
    {
    {
      type_indx = info->type_indx;
      type_indx = info->type_indx;
      ++info->type_indx;
      ++info->type_indx;
    }
    }
 
 
  name_indx = info->name_indx;
  name_indx = info->name_indx;
  ++info->name_indx;
  ++info->name_indx;
 
 
  if (name == NULL)
  if (name == NULL)
    name = "";
    name = "";
 
 
  /* If we were given a buffer, use it; otherwise, use either the
  /* If we were given a buffer, use it; otherwise, use either the
     local or the global type information, and make sure that the type
     local or the global type information, and make sure that the type
     block is started.  */
     block is started.  */
  if (buflist != NULL)
  if (buflist != NULL)
    {
    {
      if (! ieee_change_buffer (info, buflist))
      if (! ieee_change_buffer (info, buflist))
        return FALSE;
        return FALSE;
    }
    }
  else if (localp)
  else if (localp)
    {
    {
      if (! ieee_buffer_emptyp (&info->types))
      if (! ieee_buffer_emptyp (&info->types))
        {
        {
          if (! ieee_change_buffer (info, &info->types))
          if (! ieee_change_buffer (info, &info->types))
            return FALSE;
            return FALSE;
        }
        }
      else
      else
        {
        {
          if (! ieee_change_buffer (info, &info->types)
          if (! ieee_change_buffer (info, &info->types)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 1)
              || ! ieee_write_byte (info, 1)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, info->modname))
              || ! ieee_write_id (info, info->modname))
            return FALSE;
            return FALSE;
        }
        }
    }
    }
  else
  else
    {
    {
      if (! ieee_buffer_emptyp (&info->global_types))
      if (! ieee_buffer_emptyp (&info->global_types))
        {
        {
          if (! ieee_change_buffer (info, &info->global_types))
          if (! ieee_change_buffer (info, &info->global_types))
            return FALSE;
            return FALSE;
        }
        }
      else
      else
        {
        {
          if (! ieee_change_buffer (info, &info->global_types)
          if (! ieee_change_buffer (info, &info->global_types)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, ""))
              || ! ieee_write_id (info, ""))
            return FALSE;
            return FALSE;
        }
        }
    }
    }
 
 
  /* Push the new type on the type stack, write out an NN record, and
  /* Push the new type on the type stack, write out an NN record, and
     write out the start of a TY record.  The caller will then finish
     write out the start of a TY record.  The caller will then finish
     the TY record.  */
     the TY record.  */
  if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
  if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
    return FALSE;
    return FALSE;
 
 
  return (ieee_write_byte (info, (int) ieee_nn_record)
  return (ieee_write_byte (info, (int) ieee_nn_record)
          && ieee_write_number (info, name_indx)
          && ieee_write_number (info, name_indx)
          && ieee_write_id (info, name)
          && ieee_write_id (info, name)
          && ieee_write_byte (info, (int) ieee_ty_record_enum)
          && ieee_write_byte (info, (int) ieee_ty_record_enum)
          && ieee_write_number (info, type_indx)
          && ieee_write_number (info, type_indx)
          && ieee_write_byte (info, 0xce)
          && ieee_write_byte (info, 0xce)
          && ieee_write_number (info, name_indx));
          && ieee_write_number (info, name_indx));
}
}
 
 
/* Get an entry to the list of modified versions of a type.  */
/* Get an entry to the list of modified versions of a type.  */
 
 
static struct ieee_modified_type *
static struct ieee_modified_type *
ieee_get_modified_info (struct ieee_handle *info, unsigned int indx)
ieee_get_modified_info (struct ieee_handle *info, unsigned int indx)
{
{
  if (indx >= info->modified_alloc)
  if (indx >= info->modified_alloc)
    {
    {
      unsigned int nalloc;
      unsigned int nalloc;
 
 
      nalloc = info->modified_alloc;
      nalloc = info->modified_alloc;
      if (nalloc == 0)
      if (nalloc == 0)
        nalloc = 16;
        nalloc = 16;
      while (indx >= nalloc)
      while (indx >= nalloc)
        nalloc *= 2;
        nalloc *= 2;
      info->modified = ((struct ieee_modified_type *)
      info->modified = ((struct ieee_modified_type *)
                        xrealloc (info->modified,
                        xrealloc (info->modified,
                                  nalloc * sizeof *info->modified));
                                  nalloc * sizeof *info->modified));
      memset (info->modified + info->modified_alloc, 0,
      memset (info->modified + info->modified_alloc, 0,
              (nalloc - info->modified_alloc) * sizeof *info->modified);
              (nalloc - info->modified_alloc) * sizeof *info->modified);
      info->modified_alloc = nalloc;
      info->modified_alloc = nalloc;
    }
    }
 
 
  return info->modified + indx;
  return info->modified + indx;
}
}


/* Routines for the hash table mapping names to types.  */
/* Routines for the hash table mapping names to types.  */
 
 
/* Initialize an entry in the hash table.  */
/* Initialize an entry in the hash table.  */
 
 
static struct bfd_hash_entry *
static struct bfd_hash_entry *
ieee_name_type_newfunc (struct bfd_hash_entry *entry,
ieee_name_type_newfunc (struct bfd_hash_entry *entry,
                        struct bfd_hash_table *table, const char *string)
                        struct bfd_hash_table *table, const char *string)
{
{
  struct ieee_name_type_hash_entry *ret =
  struct ieee_name_type_hash_entry *ret =
    (struct ieee_name_type_hash_entry *) entry;
    (struct ieee_name_type_hash_entry *) entry;
 
 
  /* Allocate the structure if it has not already been allocated by a
  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
     subclass.  */
  if (ret == NULL)
  if (ret == NULL)
    ret = ((struct ieee_name_type_hash_entry *)
    ret = ((struct ieee_name_type_hash_entry *)
           bfd_hash_allocate (table, sizeof *ret));
           bfd_hash_allocate (table, sizeof *ret));
  if (ret == NULL)
  if (ret == NULL)
    return NULL;
    return NULL;
 
 
  /* Call the allocation method of the superclass.  */
  /* Call the allocation method of the superclass.  */
  ret = ((struct ieee_name_type_hash_entry *)
  ret = ((struct ieee_name_type_hash_entry *)
         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
  if (ret)
  if (ret)
    {
    {
      /* Set local fields.  */
      /* Set local fields.  */
      ret->types = NULL;
      ret->types = NULL;
    }
    }
 
 
  return (struct bfd_hash_entry *) ret;
  return (struct bfd_hash_entry *) ret;
}
}
 
 
/* Look up an entry in the hash table.  */
/* Look up an entry in the hash table.  */
 
 
#define ieee_name_type_hash_lookup(table, string, create, copy) \
#define ieee_name_type_hash_lookup(table, string, create, copy) \
  ((struct ieee_name_type_hash_entry *) \
  ((struct ieee_name_type_hash_entry *) \
   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
 
 
/* Traverse the hash table.  */
/* Traverse the hash table.  */
 
 
#define ieee_name_type_hash_traverse(table, func, info)                 \
#define ieee_name_type_hash_traverse(table, func, info)                 \
  (bfd_hash_traverse                                                    \
  (bfd_hash_traverse                                                    \
   (&(table)->root,                                                     \
   (&(table)->root,                                                     \
    (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func),         \
    (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func),         \
    (info)))
    (info)))


/* The general routine to write out IEEE debugging information.  */
/* The general routine to write out IEEE debugging information.  */
 
 
bfd_boolean
bfd_boolean
write_ieee_debugging_info (bfd *abfd, void *dhandle)
write_ieee_debugging_info (bfd *abfd, void *dhandle)
{
{
  struct ieee_handle info;
  struct ieee_handle info;
  asection *s;
  asection *s;
  const char *err;
  const char *err;
  struct ieee_buf *b;
  struct ieee_buf *b;
 
 
  memset (&info, 0, sizeof info);
  memset (&info, 0, sizeof info);
  info.abfd = abfd;
  info.abfd = abfd;
  info.type_indx = 256;
  info.type_indx = 256;
  info.name_indx = 32;
  info.name_indx = 32;
 
 
  if (!bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc,
  if (!bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc,
                            sizeof (struct ieee_name_type_hash_entry))
                            sizeof (struct ieee_name_type_hash_entry))
      || !bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc,
      || !bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc,
                               sizeof (struct ieee_name_type_hash_entry)))
                               sizeof (struct ieee_name_type_hash_entry)))
    return FALSE;
    return FALSE;
 
 
  if (! ieee_init_buffer (&info, &info.global_types)
  if (! ieee_init_buffer (&info, &info.global_types)
      || ! ieee_init_buffer (&info, &info.data)
      || ! ieee_init_buffer (&info, &info.data)
      || ! ieee_init_buffer (&info, &info.types)
      || ! ieee_init_buffer (&info, &info.types)
      || ! ieee_init_buffer (&info, &info.vars)
      || ! ieee_init_buffer (&info, &info.vars)
      || ! ieee_init_buffer (&info, &info.cxx)
      || ! ieee_init_buffer (&info, &info.cxx)
      || ! ieee_init_buffer (&info, &info.linenos)
      || ! ieee_init_buffer (&info, &info.linenos)
      || ! ieee_init_buffer (&info, &info.fntype)
      || ! ieee_init_buffer (&info, &info.fntype)
      || ! ieee_init_buffer (&info, &info.fnargs))
      || ! ieee_init_buffer (&info, &info.fnargs))
    return FALSE;
    return FALSE;
 
 
  if (! debug_write (dhandle, &ieee_fns, (void *) &info))
  if (! debug_write (dhandle, &ieee_fns, (void *) &info))
    return FALSE;
    return FALSE;
 
 
  if (info.filename != NULL)
  if (info.filename != NULL)
    {
    {
      if (! ieee_finish_compilation_unit (&info))
      if (! ieee_finish_compilation_unit (&info))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Put any undefined tags in the global typedef information.  */
  /* Put any undefined tags in the global typedef information.  */
  info.error = FALSE;
  info.error = FALSE;
  ieee_name_type_hash_traverse (&info.tags,
  ieee_name_type_hash_traverse (&info.tags,
                                ieee_write_undefined_tag,
                                ieee_write_undefined_tag,
                                (void *) &info);
                                (void *) &info);
  if (info.error)
  if (info.error)
    return FALSE;
    return FALSE;
 
 
  /* Prepend the global typedef information to the other data.  */
  /* Prepend the global typedef information to the other data.  */
  if (! ieee_buffer_emptyp (&info.global_types))
  if (! ieee_buffer_emptyp (&info.global_types))
    {
    {
      /* The HP debugger seems to have a bug in which it ignores the
      /* The HP debugger seems to have a bug in which it ignores the
         last entry in the global types, so we add a dummy entry.  */
         last entry in the global types, so we add a dummy entry.  */
      if (! ieee_change_buffer (&info, &info.global_types)
      if (! ieee_change_buffer (&info, &info.global_types)
          || ! ieee_write_byte (&info, (int) ieee_nn_record)
          || ! ieee_write_byte (&info, (int) ieee_nn_record)
          || ! ieee_write_number (&info, info.name_indx)
          || ! ieee_write_number (&info, info.name_indx)
          || ! ieee_write_id (&info, "")
          || ! ieee_write_id (&info, "")
          || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
          || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
          || ! ieee_write_number (&info, info.type_indx)
          || ! ieee_write_number (&info, info.type_indx)
          || ! ieee_write_byte (&info, 0xce)
          || ! ieee_write_byte (&info, 0xce)
          || ! ieee_write_number (&info, info.name_indx)
          || ! ieee_write_number (&info, info.name_indx)
          || ! ieee_write_number (&info, 'P')
          || ! ieee_write_number (&info, 'P')
          || ! ieee_write_number (&info, (int) builtin_void + 32)
          || ! ieee_write_number (&info, (int) builtin_void + 32)
          || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
          || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
        return FALSE;
        return FALSE;
 
 
      if (! ieee_append_buffer (&info, &info.global_types, &info.data))
      if (! ieee_append_buffer (&info, &info.global_types, &info.data))
        return FALSE;
        return FALSE;
      info.data = info.global_types;
      info.data = info.global_types;
    }
    }
 
 
  /* Make sure that we have declare BB11 blocks for each range in the
  /* Make sure that we have declare BB11 blocks for each range in the
     file.  They are added to info->vars.  */
     file.  They are added to info->vars.  */
  info.error = FALSE;
  info.error = FALSE;
  if (! ieee_init_buffer (&info, &info.vars))
  if (! ieee_init_buffer (&info, &info.vars))
    return FALSE;
    return FALSE;
  bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (void *) &info);
  bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (void *) &info);
  if (info.error)
  if (info.error)
    return FALSE;
    return FALSE;
  if (! ieee_buffer_emptyp (&info.vars))
  if (! ieee_buffer_emptyp (&info.vars))
    {
    {
      if (! ieee_change_buffer (&info, &info.vars)
      if (! ieee_change_buffer (&info, &info.vars)
          || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
          || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
        return FALSE;
        return FALSE;
 
 
      if (! ieee_append_buffer (&info, &info.data, &info.vars))
      if (! ieee_append_buffer (&info, &info.data, &info.vars))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* Now all the data is in info.data.  Write it out to the BFD.  We
  /* Now all the data is in info.data.  Write it out to the BFD.  We
     normally would need to worry about whether all the other sections
     normally would need to worry about whether all the other sections
     are set up yet, but the IEEE backend will handle this particular
     are set up yet, but the IEEE backend will handle this particular
     case correctly regardless.  */
     case correctly regardless.  */
  if (ieee_buffer_emptyp (&info.data))
  if (ieee_buffer_emptyp (&info.data))
    {
    {
      /* There is no debugging information.  */
      /* There is no debugging information.  */
      return TRUE;
      return TRUE;
    }
    }
  err = NULL;
  err = NULL;
  s = bfd_make_section (abfd, ".debug");
  s = bfd_make_section (abfd, ".debug");
  if (s == NULL)
  if (s == NULL)
    err = "bfd_make_section";
    err = "bfd_make_section";
  if (err == NULL)
  if (err == NULL)
    {
    {
      if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
      if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
        err = "bfd_set_section_flags";
        err = "bfd_set_section_flags";
    }
    }
  if (err == NULL)
  if (err == NULL)
    {
    {
      bfd_size_type size;
      bfd_size_type size;
 
 
      size = 0;
      size = 0;
      for (b = info.data.head; b != NULL; b = b->next)
      for (b = info.data.head; b != NULL; b = b->next)
        size += b->c;
        size += b->c;
      if (! bfd_set_section_size (abfd, s, size))
      if (! bfd_set_section_size (abfd, s, size))
        err = "bfd_set_section_size";
        err = "bfd_set_section_size";
    }
    }
  if (err == NULL)
  if (err == NULL)
    {
    {
      file_ptr offset;
      file_ptr offset;
 
 
      offset = 0;
      offset = 0;
      for (b = info.data.head; b != NULL; b = b->next)
      for (b = info.data.head; b != NULL; b = b->next)
        {
        {
          if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
          if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
            {
            {
              err = "bfd_set_section_contents";
              err = "bfd_set_section_contents";
              break;
              break;
            }
            }
          offset += b->c;
          offset += b->c;
        }
        }
    }
    }
 
 
  if (err != NULL)
  if (err != NULL)
    {
    {
      fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
      fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
               bfd_errmsg (bfd_get_error ()));
               bfd_errmsg (bfd_get_error ()));
      return FALSE;
      return FALSE;
    }
    }
 
 
  bfd_hash_table_free (&info.typedefs.root);
  bfd_hash_table_free (&info.typedefs.root);
  bfd_hash_table_free (&info.tags.root);
  bfd_hash_table_free (&info.tags.root);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Write out information for an undefined tag.  This is called via
/* Write out information for an undefined tag.  This is called via
   ieee_name_type_hash_traverse.  */
   ieee_name_type_hash_traverse.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_write_undefined_tag (struct ieee_name_type_hash_entry *h, void *p)
ieee_write_undefined_tag (struct ieee_name_type_hash_entry *h, void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_name_type *nt;
  struct ieee_name_type *nt;
 
 
  for (nt = h->types; nt != NULL; nt = nt->next)
  for (nt = h->types; nt != NULL; nt = nt->next)
    {
    {
      unsigned int name_indx;
      unsigned int name_indx;
      char code;
      char code;
 
 
      if (nt->kind == DEBUG_KIND_ILLEGAL)
      if (nt->kind == DEBUG_KIND_ILLEGAL)
        continue;
        continue;
 
 
      if (ieee_buffer_emptyp (&info->global_types))
      if (ieee_buffer_emptyp (&info->global_types))
        {
        {
          if (! ieee_change_buffer (info, &info->global_types)
          if (! ieee_change_buffer (info, &info->global_types)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, ""))
              || ! ieee_write_id (info, ""))
            {
            {
              info->error = TRUE;
              info->error = TRUE;
              return FALSE;
              return FALSE;
            }
            }
        }
        }
      else
      else
        {
        {
          if (! ieee_change_buffer (info, &info->global_types))
          if (! ieee_change_buffer (info, &info->global_types))
            {
            {
              info->error = TRUE;
              info->error = TRUE;
              return FALSE;
              return FALSE;
            }
            }
        }
        }
 
 
      name_indx = info->name_indx;
      name_indx = info->name_indx;
      ++info->name_indx;
      ++info->name_indx;
      if (! ieee_write_byte (info, (int) ieee_nn_record)
      if (! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_number (info, name_indx)
          || ! ieee_write_number (info, name_indx)
          || ! ieee_write_id (info, nt->type.name)
          || ! ieee_write_id (info, nt->type.name)
          || ! ieee_write_byte (info, (int) ieee_ty_record_enum)
          || ! ieee_write_byte (info, (int) ieee_ty_record_enum)
          || ! ieee_write_number (info, nt->type.indx)
          || ! ieee_write_number (info, nt->type.indx)
          || ! ieee_write_byte (info, 0xce)
          || ! ieee_write_byte (info, 0xce)
          || ! ieee_write_number (info, name_indx))
          || ! ieee_write_number (info, name_indx))
        {
        {
          info->error = TRUE;
          info->error = TRUE;
          return FALSE;
          return FALSE;
        }
        }
 
 
      switch (nt->kind)
      switch (nt->kind)
        {
        {
        default:
        default:
          abort ();
          abort ();
          info->error = TRUE;
          info->error = TRUE;
          return FALSE;
          return FALSE;
        case DEBUG_KIND_STRUCT:
        case DEBUG_KIND_STRUCT:
        case DEBUG_KIND_CLASS:
        case DEBUG_KIND_CLASS:
          code = 'S';
          code = 'S';
          break;
          break;
        case DEBUG_KIND_UNION:
        case DEBUG_KIND_UNION:
        case DEBUG_KIND_UNION_CLASS:
        case DEBUG_KIND_UNION_CLASS:
          code = 'U';
          code = 'U';
          break;
          break;
        case DEBUG_KIND_ENUM:
        case DEBUG_KIND_ENUM:
          code = 'E';
          code = 'E';
          break;
          break;
        }
        }
      if (! ieee_write_number (info, code)
      if (! ieee_write_number (info, code)
          || ! ieee_write_number (info, 0))
          || ! ieee_write_number (info, 0))
        {
        {
          info->error = TRUE;
          info->error = TRUE;
          return FALSE;
          return FALSE;
        }
        }
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start writing out information for a compilation unit.  */
/* Start writing out information for a compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_compilation_unit (void *p, const char *filename)
ieee_start_compilation_unit (void *p, const char *filename)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  const char *modname;
  const char *modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  const char *backslash;
  const char *backslash;
#endif
#endif
  char *c, *s;
  char *c, *s;
  unsigned int nindx;
  unsigned int nindx;
 
 
  if (info->filename != NULL)
  if (info->filename != NULL)
    {
    {
      if (! ieee_finish_compilation_unit (info))
      if (! ieee_finish_compilation_unit (info))
        return FALSE;
        return FALSE;
    }
    }
 
 
  info->filename = filename;
  info->filename = filename;
  modname = strrchr (filename, '/');
  modname = strrchr (filename, '/');
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  /* We could have a mixed forward/back slash case.  */
  /* We could have a mixed forward/back slash case.  */
  backslash = strrchr (filename, '\\');
  backslash = strrchr (filename, '\\');
  if (modname == NULL || (backslash != NULL && backslash > modname))
  if (modname == NULL || (backslash != NULL && backslash > modname))
    modname = backslash;
    modname = backslash;
#endif
#endif
 
 
  if (modname != NULL)
  if (modname != NULL)
    ++modname;
    ++modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  else if (filename[0] && filename[1] == ':')
  else if (filename[0] && filename[1] == ':')
    modname = filename + 2;
    modname = filename + 2;
#endif
#endif
  else
  else
    modname = filename;
    modname = filename;
 
 
  c = xstrdup (modname);
  c = xstrdup (modname);
  s = strrchr (c, '.');
  s = strrchr (c, '.');
  if (s != NULL)
  if (s != NULL)
    *s = '\0';
    *s = '\0';
  info->modname = c;
  info->modname = c;
 
 
  if (! ieee_init_buffer (info, &info->types)
  if (! ieee_init_buffer (info, &info->types)
      || ! ieee_init_buffer (info, &info->vars)
      || ! ieee_init_buffer (info, &info->vars)
      || ! ieee_init_buffer (info, &info->cxx)
      || ! ieee_init_buffer (info, &info->cxx)
      || ! ieee_init_buffer (info, &info->linenos))
      || ! ieee_init_buffer (info, &info->linenos))
    return FALSE;
    return FALSE;
  info->ranges = NULL;
  info->ranges = NULL;
 
 
  /* Always include a BB1 and a BB3 block.  That is what the output of
  /* Always include a BB1 and a BB3 block.  That is what the output of
     the MRI linker seems to look like.  */
     the MRI linker seems to look like.  */
  if (! ieee_change_buffer (info, &info->types)
  if (! ieee_change_buffer (info, &info->types)
      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, 1)
      || ! ieee_write_byte (info, 1)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_id (info, info->modname))
      || ! ieee_write_id (info, info->modname))
    return FALSE;
    return FALSE;
 
 
  nindx = info->name_indx;
  nindx = info->name_indx;
  ++info->name_indx;
  ++info->name_indx;
  if (! ieee_change_buffer (info, &info->vars)
  if (! ieee_change_buffer (info, &info->vars)
      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, 3)
      || ! ieee_write_byte (info, 3)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_id (info, info->modname))
      || ! ieee_write_id (info, info->modname))
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish up a compilation unit.  */
/* Finish up a compilation unit.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_finish_compilation_unit (struct ieee_handle *info)
ieee_finish_compilation_unit (struct ieee_handle *info)
{
{
  struct ieee_range *r;
  struct ieee_range *r;
 
 
  if (! ieee_buffer_emptyp (&info->types))
  if (! ieee_buffer_emptyp (&info->types))
    {
    {
      if (! ieee_change_buffer (info, &info->types)
      if (! ieee_change_buffer (info, &info->types)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_buffer_emptyp (&info->cxx))
  if (! ieee_buffer_emptyp (&info->cxx))
    {
    {
      /* Append any C++ information to the global function and
      /* Append any C++ information to the global function and
         variable information.  */
         variable information.  */
      assert (! ieee_buffer_emptyp (&info->vars));
      assert (! ieee_buffer_emptyp (&info->vars));
      if (! ieee_change_buffer (info, &info->vars))
      if (! ieee_change_buffer (info, &info->vars))
        return FALSE;
        return FALSE;
 
 
      /* We put the pmisc records in a dummy procedure, just as the
      /* We put the pmisc records in a dummy procedure, just as the
         MRI compiler does.  */
         MRI compiler does.  */
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, 6)
          || ! ieee_write_byte (info, 6)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, "__XRYCPP")
          || ! ieee_write_id (info, "__XRYCPP")
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, info->highaddr - 1)
          || ! ieee_write_number (info, info->highaddr - 1)
          || ! ieee_append_buffer (info, &info->vars, &info->cxx)
          || ! ieee_append_buffer (info, &info->vars, &info->cxx)
          || ! ieee_change_buffer (info, &info->vars)
          || ! ieee_change_buffer (info, &info->vars)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum)
          || ! ieee_write_number (info, info->highaddr - 1))
          || ! ieee_write_number (info, info->highaddr - 1))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_buffer_emptyp (&info->vars))
  if (! ieee_buffer_emptyp (&info->vars))
    {
    {
      if (! ieee_change_buffer (info, &info->vars)
      if (! ieee_change_buffer (info, &info->vars)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (info->pending_lineno_filename != NULL)
  if (info->pending_lineno_filename != NULL)
    {
    {
      /* Force out the pending line number.  */
      /* Force out the pending line number.  */
      if (! ieee_lineno ((void *) info, (const char *) NULL, 0, (bfd_vma) -1))
      if (! ieee_lineno ((void *) info, (const char *) NULL, 0, (bfd_vma) -1))
        return FALSE;
        return FALSE;
    }
    }
  if (! ieee_buffer_emptyp (&info->linenos))
  if (! ieee_buffer_emptyp (&info->linenos))
    {
    {
      if (! ieee_change_buffer (info, &info->linenos)
      if (! ieee_change_buffer (info, &info->linenos)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
          || ! ieee_write_byte (info, (int) ieee_be_record_enum))
        return FALSE;
        return FALSE;
      if (strcmp (info->filename, info->lineno_filename) != 0)
      if (strcmp (info->filename, info->lineno_filename) != 0)
        {
        {
          /* We were not in the main file.  We just closed the
          /* We were not in the main file.  We just closed the
             included line number block, and now we must close the
             included line number block, and now we must close the
             main line number block.  */
             main line number block.  */
          if (! ieee_write_byte (info, (int) ieee_be_record_enum))
          if (! ieee_write_byte (info, (int) ieee_be_record_enum))
            return FALSE;
            return FALSE;
        }
        }
    }
    }
 
 
  if (! ieee_append_buffer (info, &info->data, &info->types)
  if (! ieee_append_buffer (info, &info->data, &info->types)
      || ! ieee_append_buffer (info, &info->data, &info->vars)
      || ! ieee_append_buffer (info, &info->data, &info->vars)
      || ! ieee_append_buffer (info, &info->data, &info->linenos))
      || ! ieee_append_buffer (info, &info->data, &info->linenos))
    return FALSE;
    return FALSE;
 
 
  /* Build BB10/BB11 blocks based on the ranges we recorded.  */
  /* Build BB10/BB11 blocks based on the ranges we recorded.  */
  if (! ieee_change_buffer (info, &info->data))
  if (! ieee_change_buffer (info, &info->data))
    return FALSE;
    return FALSE;
 
 
  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, 10)
      || ! ieee_write_byte (info, 10)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_id (info, info->modname)
      || ! ieee_write_id (info, info->modname)
      || ! ieee_write_id (info, "")
      || ! ieee_write_id (info, "")
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_id (info, "GNU objcopy"))
      || ! ieee_write_id (info, "GNU objcopy"))
    return FALSE;
    return FALSE;
 
 
  for (r = info->ranges; r != NULL; r = r->next)
  for (r = info->ranges; r != NULL; r = r->next)
    {
    {
      bfd_vma low, high;
      bfd_vma low, high;
      asection *s;
      asection *s;
      int kind;
      int kind;
 
 
      low = r->low;
      low = r->low;
      high = r->high;
      high = r->high;
 
 
      /* Find the section corresponding to this range.  */
      /* Find the section corresponding to this range.  */
      for (s = info->abfd->sections; s != NULL; s = s->next)
      for (s = info->abfd->sections; s != NULL; s = s->next)
        {
        {
          if (bfd_get_section_vma (info->abfd, s) <= low
          if (bfd_get_section_vma (info->abfd, s) <= low
              && high <= (bfd_get_section_vma (info->abfd, s)
              && high <= (bfd_get_section_vma (info->abfd, s)
                          + bfd_section_size (info->abfd, s)))
                          + bfd_section_size (info->abfd, s)))
            break;
            break;
        }
        }
 
 
      if (s == NULL)
      if (s == NULL)
        {
        {
          /* Just ignore this range.  */
          /* Just ignore this range.  */
          continue;
          continue;
        }
        }
 
 
      /* Coalesce ranges if it seems reasonable.  */
      /* Coalesce ranges if it seems reasonable.  */
      while (r->next != NULL
      while (r->next != NULL
             && high + 0x1000 >= r->next->low
             && high + 0x1000 >= r->next->low
             && (r->next->high
             && (r->next->high
                 <= (bfd_get_section_vma (info->abfd, s)
                 <= (bfd_get_section_vma (info->abfd, s)
                     + bfd_section_size (info->abfd, s))))
                     + bfd_section_size (info->abfd, s))))
        {
        {
          r = r->next;
          r = r->next;
          high = r->high;
          high = r->high;
        }
        }
 
 
      if ((s->flags & SEC_CODE) != 0)
      if ((s->flags & SEC_CODE) != 0)
        kind = 1;
        kind = 1;
      else if ((s->flags & SEC_READONLY) != 0)
      else if ((s->flags & SEC_READONLY) != 0)
        kind = 3;
        kind = 3;
      else
      else
        kind = 2;
        kind = 2;
 
 
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, 11)
          || ! ieee_write_byte (info, 11)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_number (info, kind)
          || ! ieee_write_number (info, kind)
          || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
          || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
          || ! ieee_write_number (info, low)
          || ! ieee_write_number (info, low)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum)
          || ! ieee_write_byte (info, (int) ieee_be_record_enum)
          || ! ieee_write_number (info, high - low))
          || ! ieee_write_number (info, high - low))
        return FALSE;
        return FALSE;
 
 
      /* Add this range to the list of global ranges.  */
      /* Add this range to the list of global ranges.  */
      if (! ieee_add_range (info, TRUE, low, high))
      if (! ieee_add_range (info, TRUE, low, high))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_write_byte (info, (int) ieee_be_record_enum))
  if (! ieee_write_byte (info, (int) ieee_be_record_enum))
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add BB11 blocks describing each range that we have not already
/* Add BB11 blocks describing each range that we have not already
   described.  */
   described.  */
 
 
static void
static void
ieee_add_bb11_blocks (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *data)
ieee_add_bb11_blocks (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *data)
{
{
  struct ieee_handle *info = (struct ieee_handle *) data;
  struct ieee_handle *info = (struct ieee_handle *) data;
  bfd_vma low, high;
  bfd_vma low, high;
  struct ieee_range *r;
  struct ieee_range *r;
 
 
  low = bfd_get_section_vma (abfd, sec);
  low = bfd_get_section_vma (abfd, sec);
  high = low + bfd_section_size (abfd, sec);
  high = low + bfd_section_size (abfd, sec);
 
 
  /* Find the first range at or after this section.  The ranges are
  /* Find the first range at or after this section.  The ranges are
     sorted by address.  */
     sorted by address.  */
  for (r = info->global_ranges; r != NULL; r = r->next)
  for (r = info->global_ranges; r != NULL; r = r->next)
    if (r->high > low)
    if (r->high > low)
      break;
      break;
 
 
  while (low < high)
  while (low < high)
    {
    {
      if (r == NULL || r->low >= high)
      if (r == NULL || r->low >= high)
        {
        {
          if (! ieee_add_bb11 (info, sec, low, high))
          if (! ieee_add_bb11 (info, sec, low, high))
            info->error = TRUE;
            info->error = TRUE;
          return;
          return;
        }
        }
 
 
      if (low < r->low
      if (low < r->low
          && r->low - low > 0x100)
          && r->low - low > 0x100)
        {
        {
          if (! ieee_add_bb11 (info, sec, low, r->low))
          if (! ieee_add_bb11 (info, sec, low, r->low))
            {
            {
              info->error = TRUE;
              info->error = TRUE;
              return;
              return;
            }
            }
        }
        }
      low = r->high;
      low = r->high;
 
 
      r = r->next;
      r = r->next;
    }
    }
}
}
 
 
/* Add a single BB11 block for a range.  We add it to info->vars.  */
/* Add a single BB11 block for a range.  We add it to info->vars.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_add_bb11 (struct ieee_handle *info, asection *sec, bfd_vma low,
ieee_add_bb11 (struct ieee_handle *info, asection *sec, bfd_vma low,
               bfd_vma high)
               bfd_vma high)
{
{
  int kind;
  int kind;
 
 
  if (! ieee_buffer_emptyp (&info->vars))
  if (! ieee_buffer_emptyp (&info->vars))
    {
    {
      if (! ieee_change_buffer (info, &info->vars))
      if (! ieee_change_buffer (info, &info->vars))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      const char *filename, *modname;
      const char *filename, *modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
      const char *backslash;
      const char *backslash;
#endif
#endif
      char *c, *s;
      char *c, *s;
 
 
      /* Start the enclosing BB10 block.  */
      /* Start the enclosing BB10 block.  */
      filename = bfd_get_filename (info->abfd);
      filename = bfd_get_filename (info->abfd);
      modname = strrchr (filename, '/');
      modname = strrchr (filename, '/');
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
      backslash = strrchr (filename, '\\');
      backslash = strrchr (filename, '\\');
      if (modname == NULL || (backslash != NULL && backslash > modname))
      if (modname == NULL || (backslash != NULL && backslash > modname))
        modname = backslash;
        modname = backslash;
#endif
#endif
 
 
      if (modname != NULL)
      if (modname != NULL)
        ++modname;
        ++modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
      else if (filename[0] && filename[1] == ':')
      else if (filename[0] && filename[1] == ':')
        modname = filename + 2;
        modname = filename + 2;
#endif
#endif
      else
      else
        modname = filename;
        modname = filename;
 
 
      c = xstrdup (modname);
      c = xstrdup (modname);
      s = strrchr (c, '.');
      s = strrchr (c, '.');
      if (s != NULL)
      if (s != NULL)
        *s = '\0';
        *s = '\0';
 
 
      if (! ieee_change_buffer (info, &info->vars)
      if (! ieee_change_buffer (info, &info->vars)
          || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, 10)
          || ! ieee_write_byte (info, 10)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, c)
          || ! ieee_write_id (info, c)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, "GNU objcopy"))
          || ! ieee_write_id (info, "GNU objcopy"))
        return FALSE;
        return FALSE;
 
 
      free (c);
      free (c);
    }
    }
 
 
  if ((sec->flags & SEC_CODE) != 0)
  if ((sec->flags & SEC_CODE) != 0)
    kind = 1;
    kind = 1;
  else if ((sec->flags & SEC_READONLY) != 0)
  else if ((sec->flags & SEC_READONLY) != 0)
    kind = 3;
    kind = 3;
  else
  else
    kind = 2;
    kind = 2;
 
 
  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
      || ! ieee_write_byte (info, 11)
      || ! ieee_write_byte (info, 11)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_id (info, "")
      || ! ieee_write_id (info, "")
      || ! ieee_write_number (info, kind)
      || ! ieee_write_number (info, kind)
      || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
      || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
      || ! ieee_write_number (info, low)
      || ! ieee_write_number (info, low)
      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
      || ! ieee_write_number (info, high - low))
      || ! ieee_write_number (info, high - low))
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start recording information from a particular source file.  This is
/* Start recording information from a particular source file.  This is
   used to record which file defined which types, variables, etc.  It
   used to record which file defined which types, variables, etc.  It
   is not used for line numbers, since the lineno entry point passes
   is not used for line numbers, since the lineno entry point passes
   down the file name anyhow.  IEEE debugging information doesn't seem
   down the file name anyhow.  IEEE debugging information doesn't seem
   to store this information anywhere.  */
   to store this information anywhere.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_source (void *p ATTRIBUTE_UNUSED,
ieee_start_source (void *p ATTRIBUTE_UNUSED,
                   const char *filename ATTRIBUTE_UNUSED)
                   const char *filename ATTRIBUTE_UNUSED)
{
{
  return TRUE;
  return TRUE;
}
}
 
 
/* Make an empty type.  */
/* Make an empty type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_empty_type (void *p)
ieee_empty_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  return ieee_push_type (info, (int) builtin_unknown, 0, FALSE, FALSE);
  return ieee_push_type (info, (int) builtin_unknown, 0, FALSE, FALSE);
}
}
 
 
/* Make a void type.  */
/* Make a void type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_void_type (void *p)
ieee_void_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  return ieee_push_type (info, (int) builtin_void, 0, FALSE, FALSE);
  return ieee_push_type (info, (int) builtin_void, 0, FALSE, FALSE);
}
}
 
 
/* Make an integer type.  */
/* Make an integer type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
ieee_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int indx;
  unsigned int indx;
 
 
  switch (size)
  switch (size)
    {
    {
    case 1:
    case 1:
      indx = (int) builtin_signed_char;
      indx = (int) builtin_signed_char;
      break;
      break;
    case 2:
    case 2:
      indx = (int) builtin_signed_short_int;
      indx = (int) builtin_signed_short_int;
      break;
      break;
    case 4:
    case 4:
      indx = (int) builtin_signed_long;
      indx = (int) builtin_signed_long;
      break;
      break;
    case 8:
    case 8:
      indx = (int) builtin_signed_long_long;
      indx = (int) builtin_signed_long_long;
      break;
      break;
    default:
    default:
      fprintf (stderr, _("IEEE unsupported integer type size %u\n"), size);
      fprintf (stderr, _("IEEE unsupported integer type size %u\n"), size);
      return FALSE;
      return FALSE;
    }
    }
 
 
  if (unsignedp)
  if (unsignedp)
    ++indx;
    ++indx;
 
 
  return ieee_push_type (info, indx, size, unsignedp, FALSE);
  return ieee_push_type (info, indx, size, unsignedp, FALSE);
}
}
 
 
/* Make a floating point type.  */
/* Make a floating point type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_float_type (void *p, unsigned int size)
ieee_float_type (void *p, unsigned int size)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int indx;
  unsigned int indx;
 
 
  switch (size)
  switch (size)
    {
    {
    case 4:
    case 4:
      indx = (int) builtin_float;
      indx = (int) builtin_float;
      break;
      break;
    case 8:
    case 8:
      indx = (int) builtin_double;
      indx = (int) builtin_double;
      break;
      break;
    case 12:
    case 12:
      /* FIXME: This size really depends upon the processor.  */
      /* FIXME: This size really depends upon the processor.  */
      indx = (int) builtin_long_double;
      indx = (int) builtin_long_double;
      break;
      break;
    case 16:
    case 16:
      indx = (int) builtin_long_long_double;
      indx = (int) builtin_long_long_double;
      break;
      break;
    default:
    default:
      fprintf (stderr, _("IEEE unsupported float type size %u\n"), size);
      fprintf (stderr, _("IEEE unsupported float type size %u\n"), size);
      return FALSE;
      return FALSE;
    }
    }
 
 
  return ieee_push_type (info, indx, size, FALSE, FALSE);
  return ieee_push_type (info, indx, size, FALSE, FALSE);
}
}
 
 
/* Make a complex type.  */
/* Make a complex type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_complex_type (void *p, unsigned int size)
ieee_complex_type (void *p, unsigned int size)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  char code;
  char code;
 
 
  switch (size)
  switch (size)
    {
    {
    case 4:
    case 4:
      if (info->complex_float_index != 0)
      if (info->complex_float_index != 0)
        return ieee_push_type (info, info->complex_float_index, size * 2,
        return ieee_push_type (info, info->complex_float_index, size * 2,
                               FALSE, FALSE);
                               FALSE, FALSE);
      code = 'c';
      code = 'c';
      break;
      break;
    case 12:
    case 12:
    case 16:
    case 16:
      /* These cases can be output by gcc -gstabs.  Outputting the
      /* These cases can be output by gcc -gstabs.  Outputting the
         wrong type is better than crashing.  */
         wrong type is better than crashing.  */
    case 8:
    case 8:
      if (info->complex_double_index != 0)
      if (info->complex_double_index != 0)
        return ieee_push_type (info, info->complex_double_index, size * 2,
        return ieee_push_type (info, info->complex_double_index, size * 2,
                               FALSE, FALSE);
                               FALSE, FALSE);
      code = 'd';
      code = 'd';
      break;
      break;
    default:
    default:
      fprintf (stderr, _("IEEE unsupported complex type size %u\n"), size);
      fprintf (stderr, _("IEEE unsupported complex type size %u\n"), size);
      return FALSE;
      return FALSE;
    }
    }
 
 
  /* FIXME: I don't know what the string is for.  */
  /* FIXME: I don't know what the string is for.  */
  if (! ieee_define_type (info, size * 2, FALSE, FALSE)
  if (! ieee_define_type (info, size * 2, FALSE, FALSE)
      || ! ieee_write_number (info, code)
      || ! ieee_write_number (info, code)
      || ! ieee_write_id (info, ""))
      || ! ieee_write_id (info, ""))
    return FALSE;
    return FALSE;
 
 
  if (size == 4)
  if (size == 4)
    info->complex_float_index = info->type_stack->type.indx;
    info->complex_float_index = info->type_stack->type.indx;
  else
  else
    info->complex_double_index = info->type_stack->type.indx;
    info->complex_double_index = info->type_stack->type.indx;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a boolean type.  IEEE doesn't support these, so we just make
/* Make a boolean type.  IEEE doesn't support these, so we just make
   an integer type instead.  */
   an integer type instead.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_bool_type (void *p, unsigned int size)
ieee_bool_type (void *p, unsigned int size)
{
{
  return ieee_int_type (p, size, TRUE);
  return ieee_int_type (p, size, TRUE);
}
}
 
 
/* Make an enumeration.  */
/* Make an enumeration.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_enum_type (void *p, const char *tag, const char **names,
ieee_enum_type (void *p, const char *tag, const char **names,
                bfd_signed_vma *vals)
                bfd_signed_vma *vals)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_defined_enum *e;
  struct ieee_defined_enum *e;
  bfd_boolean localp, simple;
  bfd_boolean localp, simple;
  unsigned int indx;
  unsigned int indx;
  int i = 0;
  int i = 0;
 
 
  localp = FALSE;
  localp = FALSE;
  indx = (unsigned int) -1;
  indx = (unsigned int) -1;
  for (e = info->enums; e != NULL; e = e->next)
  for (e = info->enums; e != NULL; e = e->next)
    {
    {
      if (tag == NULL)
      if (tag == NULL)
        {
        {
          if (e->tag != NULL)
          if (e->tag != NULL)
            continue;
            continue;
        }
        }
      else
      else
        {
        {
          if (e->tag == NULL
          if (e->tag == NULL
              || tag[0] != e->tag[0]
              || tag[0] != e->tag[0]
              || strcmp (tag, e->tag) != 0)
              || strcmp (tag, e->tag) != 0)
            continue;
            continue;
        }
        }
 
 
      if (! e->defined)
      if (! e->defined)
        {
        {
          /* This enum tag has been seen but not defined.  */
          /* This enum tag has been seen but not defined.  */
          indx = e->indx;
          indx = e->indx;
          break;
          break;
        }
        }
 
 
      if (names != NULL && e->names != NULL)
      if (names != NULL && e->names != NULL)
        {
        {
          for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
          for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
            {
            {
              if (names[i][0] != e->names[i][0]
              if (names[i][0] != e->names[i][0]
                  || vals[i] != e->vals[i]
                  || vals[i] != e->vals[i]
                  || strcmp (names[i], e->names[i]) != 0)
                  || strcmp (names[i], e->names[i]) != 0)
                break;
                break;
            }
            }
        }
        }
 
 
      if ((names == NULL && e->names == NULL)
      if ((names == NULL && e->names == NULL)
          || (names != NULL
          || (names != NULL
              && e->names != NULL
              && e->names != NULL
              && names[i] == NULL
              && names[i] == NULL
              && e->names[i] == NULL))
              && e->names[i] == NULL))
        {
        {
          /* We've seen this enum before.  */
          /* We've seen this enum before.  */
          return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
          return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
        }
        }
 
 
      if (tag != NULL)
      if (tag != NULL)
        {
        {
          /* We've already seen an enum of the same name, so we must make
          /* We've already seen an enum of the same name, so we must make
             sure to output this one locally.  */
             sure to output this one locally.  */
          localp = TRUE;
          localp = TRUE;
          break;
          break;
        }
        }
    }
    }
 
 
  /* If this is a simple enumeration, in which the values start at 0
  /* If this is a simple enumeration, in which the values start at 0
     and always increment by 1, we can use type E.  Otherwise we must
     and always increment by 1, we can use type E.  Otherwise we must
     use type N.  */
     use type N.  */
 
 
  simple = TRUE;
  simple = TRUE;
  if (names != NULL)
  if (names != NULL)
    {
    {
      for (i = 0; names[i] != NULL; i++)
      for (i = 0; names[i] != NULL; i++)
        {
        {
          if (vals[i] != i)
          if (vals[i] != i)
            {
            {
              simple = FALSE;
              simple = FALSE;
              break;
              break;
            }
            }
        }
        }
    }
    }
 
 
  if (! ieee_define_named_type (info, tag, indx, 0, TRUE, localp,
  if (! ieee_define_named_type (info, tag, indx, 0, TRUE, localp,
                                (struct ieee_buflist *) NULL)
                                (struct ieee_buflist *) NULL)
      || ! ieee_write_number (info, simple ? 'E' : 'N'))
      || ! ieee_write_number (info, simple ? 'E' : 'N'))
    return FALSE;
    return FALSE;
  if (simple)
  if (simple)
    {
    {
      /* FIXME: This is supposed to be the enumeration size, but we
      /* FIXME: This is supposed to be the enumeration size, but we
         don't store that.  */
         don't store that.  */
      if (! ieee_write_number (info, 4))
      if (! ieee_write_number (info, 4))
        return FALSE;
        return FALSE;
    }
    }
  if (names != NULL)
  if (names != NULL)
    {
    {
      for (i = 0; names[i] != NULL; i++)
      for (i = 0; names[i] != NULL; i++)
        {
        {
          if (! ieee_write_id (info, names[i]))
          if (! ieee_write_id (info, names[i]))
            return FALSE;
            return FALSE;
          if (! simple)
          if (! simple)
            {
            {
              if (! ieee_write_number (info, vals[i]))
              if (! ieee_write_number (info, vals[i]))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
    }
    }
 
 
  if (! localp)
  if (! localp)
    {
    {
      if (indx == (unsigned int) -1)
      if (indx == (unsigned int) -1)
        {
        {
          e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
          e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
          memset (e, 0, sizeof *e);
          memset (e, 0, sizeof *e);
          e->indx = info->type_stack->type.indx;
          e->indx = info->type_stack->type.indx;
          e->tag = tag;
          e->tag = tag;
 
 
          e->next = info->enums;
          e->next = info->enums;
          info->enums = e;
          info->enums = e;
        }
        }
 
 
      e->names = names;
      e->names = names;
      e->vals = vals;
      e->vals = vals;
      e->defined = TRUE;
      e->defined = TRUE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a pointer type.  */
/* Make a pointer type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_pointer_type (void *p)
ieee_pointer_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int indx;
  unsigned int indx;
  struct ieee_modified_type *m = NULL;
  struct ieee_modified_type *m = NULL;
 
 
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  indx = ieee_pop_type (info);
  indx = ieee_pop_type (info);
 
 
  /* A pointer to a simple builtin type can be obtained by adding 32.
  /* A pointer to a simple builtin type can be obtained by adding 32.
     FIXME: Will this be a short pointer, and will that matter?  */
     FIXME: Will this be a short pointer, and will that matter?  */
  if (indx < 32)
  if (indx < 32)
    return ieee_push_type (info, indx + 32, 0, TRUE, FALSE);
    return ieee_push_type (info, indx + 32, 0, TRUE, FALSE);
 
 
  if (! localp)
  if (! localp)
    {
    {
      m = ieee_get_modified_info (p, indx);
      m = ieee_get_modified_info (p, indx);
      if (m == NULL)
      if (m == NULL)
        return FALSE;
        return FALSE;
 
 
      /* FIXME: The size should depend upon the architecture.  */
      /* FIXME: The size should depend upon the architecture.  */
      if (m->pointer > 0)
      if (m->pointer > 0)
        return ieee_push_type (info, m->pointer, 4, TRUE, FALSE);
        return ieee_push_type (info, m->pointer, 4, TRUE, FALSE);
    }
    }
 
 
  if (! ieee_define_type (info, 4, TRUE, localp)
  if (! ieee_define_type (info, 4, TRUE, localp)
      || ! ieee_write_number (info, 'P')
      || ! ieee_write_number (info, 'P')
      || ! ieee_write_number (info, indx))
      || ! ieee_write_number (info, indx))
    return FALSE;
    return FALSE;
 
 
  if (! localp)
  if (! localp)
    m->pointer = info->type_stack->type.indx;
    m->pointer = info->type_stack->type.indx;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a function type.  This will be called for a method, but we
/* Make a function type.  This will be called for a method, but we
   don't want to actually add it to the type table in that case.  We
   don't want to actually add it to the type table in that case.  We
   handle this by defining the type in a private buffer, and only
   handle this by defining the type in a private buffer, and only
   adding that buffer to the typedef block if we are going to use it.  */
   adding that buffer to the typedef block if we are going to use it.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_function_type (void *p, int argcount, bfd_boolean varargs)
ieee_function_type (void *p, int argcount, bfd_boolean varargs)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int *args = NULL;
  unsigned int *args = NULL;
  int i;
  int i;
  unsigned int retindx;
  unsigned int retindx;
  struct ieee_buflist fndef;
  struct ieee_buflist fndef;
  struct ieee_modified_type *m;
  struct ieee_modified_type *m;
 
 
  localp = FALSE;
  localp = FALSE;
 
 
  if (argcount > 0)
  if (argcount > 0)
    {
    {
      args = (unsigned int *) xmalloc (argcount * sizeof *args);
      args = (unsigned int *) xmalloc (argcount * sizeof *args);
      for (i = argcount - 1; i >= 0; i--)
      for (i = argcount - 1; i >= 0; i--)
        {
        {
          if (info->type_stack->type.localp)
          if (info->type_stack->type.localp)
            localp = TRUE;
            localp = TRUE;
          args[i] = ieee_pop_type (info);
          args[i] = ieee_pop_type (info);
        }
        }
    }
    }
  else if (argcount < 0)
  else if (argcount < 0)
    varargs = FALSE;
    varargs = FALSE;
 
 
  if (info->type_stack->type.localp)
  if (info->type_stack->type.localp)
    localp = TRUE;
    localp = TRUE;
  retindx = ieee_pop_type (info);
  retindx = ieee_pop_type (info);
 
 
  m = NULL;
  m = NULL;
  if (argcount < 0 && ! localp)
  if (argcount < 0 && ! localp)
    {
    {
      m = ieee_get_modified_info (p, retindx);
      m = ieee_get_modified_info (p, retindx);
      if (m == NULL)
      if (m == NULL)
        return FALSE;
        return FALSE;
 
 
      if (m->function > 0)
      if (m->function > 0)
        return ieee_push_type (info, m->function, 0, TRUE, FALSE);
        return ieee_push_type (info, m->function, 0, TRUE, FALSE);
    }
    }
 
 
  /* An attribute of 0x41 means that the frame and push mask are
  /* An attribute of 0x41 means that the frame and push mask are
     unknown.  */
     unknown.  */
  if (! ieee_init_buffer (info, &fndef)
  if (! ieee_init_buffer (info, &fndef)
      || ! ieee_define_named_type (info, (const char *) NULL,
      || ! ieee_define_named_type (info, (const char *) NULL,
                                   (unsigned int) -1, 0, TRUE, localp,
                                   (unsigned int) -1, 0, TRUE, localp,
                                   &fndef)
                                   &fndef)
      || ! ieee_write_number (info, 'x')
      || ! ieee_write_number (info, 'x')
      || ! ieee_write_number (info, 0x41)
      || ! ieee_write_number (info, 0x41)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, retindx)
      || ! ieee_write_number (info, retindx)
      || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
      || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
    return FALSE;
    return FALSE;
  if (argcount > 0)
  if (argcount > 0)
    {
    {
      for (i = 0; i < argcount; i++)
      for (i = 0; i < argcount; i++)
        if (! ieee_write_number (info, args[i]))
        if (! ieee_write_number (info, args[i]))
          return FALSE;
          return FALSE;
      free (args);
      free (args);
    }
    }
  if (varargs)
  if (varargs)
    {
    {
      /* A varargs function is represented by writing out the last
      /* A varargs function is represented by writing out the last
         argument as type void *, although this makes little sense.  */
         argument as type void *, although this makes little sense.  */
      if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
      if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_write_number (info, 0))
  if (! ieee_write_number (info, 0))
    return FALSE;
    return FALSE;
 
 
  /* We wrote the information into fndef, in case we don't need it.
  /* We wrote the information into fndef, in case we don't need it.
     It will be appended to info->types by ieee_pop_type.  */
     It will be appended to info->types by ieee_pop_type.  */
  info->type_stack->type.fndef = fndef;
  info->type_stack->type.fndef = fndef;
 
 
  if (m != NULL)
  if (m != NULL)
    m->function = info->type_stack->type.indx;
    m->function = info->type_stack->type.indx;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a reference type.  */
/* Make a reference type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_reference_type (void *p)
ieee_reference_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  /* IEEE appears to record a normal pointer type, and then use a
  /* IEEE appears to record a normal pointer type, and then use a
     pmisc record to indicate that it is really a reference.  */
     pmisc record to indicate that it is really a reference.  */
 
 
  if (! ieee_pointer_type (p))
  if (! ieee_pointer_type (p))
    return FALSE;
    return FALSE;
  info->type_stack->type.referencep = TRUE;
  info->type_stack->type.referencep = TRUE;
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a range type.  */
/* Make a range type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
ieee_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int size;
  unsigned int size;
  bfd_boolean unsignedp, localp;
  bfd_boolean unsignedp, localp;
 
 
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  unsignedp = info->type_stack->type.unsignedp;
  unsignedp = info->type_stack->type.unsignedp;
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  ieee_pop_unused_type (info);
  ieee_pop_unused_type (info);
  return (ieee_define_type (info, size, unsignedp, localp)
  return (ieee_define_type (info, size, unsignedp, localp)
          && ieee_write_number (info, 'R')
          && ieee_write_number (info, 'R')
          && ieee_write_number (info, (bfd_vma) low)
          && ieee_write_number (info, (bfd_vma) low)
          && ieee_write_number (info, (bfd_vma) high)
          && ieee_write_number (info, (bfd_vma) high)
          && ieee_write_number (info, unsignedp ? 0 : 1)
          && ieee_write_number (info, unsignedp ? 0 : 1)
          && ieee_write_number (info, size));
          && ieee_write_number (info, size));
}
}
 
 
/* Make an array type.  */
/* Make an array type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
ieee_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
                 bfd_boolean stringp ATTRIBUTE_UNUSED)
                 bfd_boolean stringp ATTRIBUTE_UNUSED)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int eleindx;
  unsigned int eleindx;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int size;
  unsigned int size;
  struct ieee_modified_type *m = NULL;
  struct ieee_modified_type *m = NULL;
  struct ieee_modified_array_type *a;
  struct ieee_modified_array_type *a;
 
 
  /* IEEE does not store the range, so we just ignore it.  */
  /* IEEE does not store the range, so we just ignore it.  */
  ieee_pop_unused_type (info);
  ieee_pop_unused_type (info);
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  eleindx = ieee_pop_type (info);
  eleindx = ieee_pop_type (info);
 
 
  /* If we don't know the range, treat the size as exactly one
  /* If we don't know the range, treat the size as exactly one
     element.  */
     element.  */
  if (low < high)
  if (low < high)
    size *= (high - low) + 1;
    size *= (high - low) + 1;
 
 
  if (! localp)
  if (! localp)
    {
    {
      m = ieee_get_modified_info (info, eleindx);
      m = ieee_get_modified_info (info, eleindx);
      if (m == NULL)
      if (m == NULL)
        return FALSE;
        return FALSE;
 
 
      for (a = m->arrays; a != NULL; a = a->next)
      for (a = m->arrays; a != NULL; a = a->next)
        {
        {
          if (a->low == low && a->high == high)
          if (a->low == low && a->high == high)
            return ieee_push_type (info, a->indx, size, FALSE, FALSE);
            return ieee_push_type (info, a->indx, size, FALSE, FALSE);
        }
        }
    }
    }
 
 
  if (! ieee_define_type (info, size, FALSE, localp)
  if (! ieee_define_type (info, size, FALSE, localp)
      || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
      || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
      || ! ieee_write_number (info, eleindx))
      || ! ieee_write_number (info, eleindx))
    return FALSE;
    return FALSE;
  if (low != 0)
  if (low != 0)
    {
    {
      if (! ieee_write_number (info, low))
      if (! ieee_write_number (info, low))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_write_number (info, high + 1))
  if (! ieee_write_number (info, high + 1))
    return FALSE;
    return FALSE;
 
 
  if (! localp)
  if (! localp)
    {
    {
      a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
      a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
      memset (a, 0, sizeof *a);
      memset (a, 0, sizeof *a);
 
 
      a->indx = info->type_stack->type.indx;
      a->indx = info->type_stack->type.indx;
      a->low = low;
      a->low = low;
      a->high = high;
      a->high = high;
 
 
      a->next = m->arrays;
      a->next = m->arrays;
      m->arrays = a;
      m->arrays = a;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a set type.  */
/* Make a set type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_set_type (void *p, bfd_boolean bitstringp ATTRIBUTE_UNUSED)
ieee_set_type (void *p, bfd_boolean bitstringp ATTRIBUTE_UNUSED)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int eleindx;
  unsigned int eleindx;
 
 
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  eleindx = ieee_pop_type (info);
  eleindx = ieee_pop_type (info);
 
 
  /* FIXME: We don't know the size, so we just use 4.  */
  /* FIXME: We don't know the size, so we just use 4.  */
 
 
  return (ieee_define_type (info, 0, TRUE, localp)
  return (ieee_define_type (info, 0, TRUE, localp)
          && ieee_write_number (info, 's')
          && ieee_write_number (info, 's')
          && ieee_write_number (info, 4)
          && ieee_write_number (info, 4)
          && ieee_write_number (info, eleindx));
          && ieee_write_number (info, eleindx));
}
}
 
 
/* Make an offset type.  */
/* Make an offset type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_offset_type (void *p)
ieee_offset_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int targetindx, baseindx;
  unsigned int targetindx, baseindx;
 
 
  targetindx = ieee_pop_type (info);
  targetindx = ieee_pop_type (info);
  baseindx = ieee_pop_type (info);
  baseindx = ieee_pop_type (info);
 
 
  /* FIXME: The MRI C++ compiler does not appear to generate any
  /* FIXME: The MRI C++ compiler does not appear to generate any
     useful type information about an offset type.  It just records a
     useful type information about an offset type.  It just records a
     pointer to member as an integer.  The MRI/HP IEEE spec does
     pointer to member as an integer.  The MRI/HP IEEE spec does
     describe a pmisc record which can be used for a pointer to
     describe a pmisc record which can be used for a pointer to
     member.  Unfortunately, it does not describe the target type,
     member.  Unfortunately, it does not describe the target type,
     which seems pretty important.  I'm going to punt this for now.  */
     which seems pretty important.  I'm going to punt this for now.  */
 
 
  return ieee_int_type (p, 4, TRUE);
  return ieee_int_type (p, 4, TRUE);
}
}
 
 
/* Make a method type.  */
/* Make a method type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_method_type (void *p, bfd_boolean domain, int argcount,
ieee_method_type (void *p, bfd_boolean domain, int argcount,
                  bfd_boolean varargs)
                  bfd_boolean varargs)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a
  /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a
     method, but the definition is incomplete.  We just output an 'x'
     method, but the definition is incomplete.  We just output an 'x'
     type.  */
     type.  */
 
 
  if (domain)
  if (domain)
    ieee_pop_unused_type (info);
    ieee_pop_unused_type (info);
 
 
  return ieee_function_type (p, argcount, varargs);
  return ieee_function_type (p, argcount, varargs);
}
}
 
 
/* Make a const qualified type.  */
/* Make a const qualified type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_const_type (void *p)
ieee_const_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int size;
  unsigned int size;
  bfd_boolean unsignedp, localp;
  bfd_boolean unsignedp, localp;
  unsigned int indx;
  unsigned int indx;
  struct ieee_modified_type *m = NULL;
  struct ieee_modified_type *m = NULL;
 
 
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  unsignedp = info->type_stack->type.unsignedp;
  unsignedp = info->type_stack->type.unsignedp;
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  indx = ieee_pop_type (info);
  indx = ieee_pop_type (info);
 
 
  if (! localp)
  if (! localp)
    {
    {
      m = ieee_get_modified_info (info, indx);
      m = ieee_get_modified_info (info, indx);
      if (m == NULL)
      if (m == NULL)
        return FALSE;
        return FALSE;
 
 
      if (m->const_qualified > 0)
      if (m->const_qualified > 0)
        return ieee_push_type (info, m->const_qualified, size, unsignedp,
        return ieee_push_type (info, m->const_qualified, size, unsignedp,
                               FALSE);
                               FALSE);
    }
    }
 
 
  if (! ieee_define_type (info, size, unsignedp, localp)
  if (! ieee_define_type (info, size, unsignedp, localp)
      || ! ieee_write_number (info, 'n')
      || ! ieee_write_number (info, 'n')
      || ! ieee_write_number (info, 1)
      || ! ieee_write_number (info, 1)
      || ! ieee_write_number (info, indx))
      || ! ieee_write_number (info, indx))
    return FALSE;
    return FALSE;
 
 
  if (! localp)
  if (! localp)
    m->const_qualified = info->type_stack->type.indx;
    m->const_qualified = info->type_stack->type.indx;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Make a volatile qualified type.  */
/* Make a volatile qualified type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_volatile_type (void *p)
ieee_volatile_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int size;
  unsigned int size;
  bfd_boolean unsignedp, localp;
  bfd_boolean unsignedp, localp;
  unsigned int indx;
  unsigned int indx;
  struct ieee_modified_type *m = NULL;
  struct ieee_modified_type *m = NULL;
 
 
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  unsignedp = info->type_stack->type.unsignedp;
  unsignedp = info->type_stack->type.unsignedp;
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  indx = ieee_pop_type (info);
  indx = ieee_pop_type (info);
 
 
  if (! localp)
  if (! localp)
    {
    {
      m = ieee_get_modified_info (info, indx);
      m = ieee_get_modified_info (info, indx);
      if (m == NULL)
      if (m == NULL)
        return FALSE;
        return FALSE;
 
 
      if (m->volatile_qualified > 0)
      if (m->volatile_qualified > 0)
        return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
        return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
                               FALSE);
                               FALSE);
    }
    }
 
 
  if (! ieee_define_type (info, size, unsignedp, localp)
  if (! ieee_define_type (info, size, unsignedp, localp)
      || ! ieee_write_number (info, 'n')
      || ! ieee_write_number (info, 'n')
      || ! ieee_write_number (info, 2)
      || ! ieee_write_number (info, 2)
      || ! ieee_write_number (info, indx))
      || ! ieee_write_number (info, indx))
    return FALSE;
    return FALSE;
 
 
  if (! localp)
  if (! localp)
    m->volatile_qualified = info->type_stack->type.indx;
    m->volatile_qualified = info->type_stack->type.indx;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Convert an enum debug_visibility into a CXXFLAGS value.  */
/* Convert an enum debug_visibility into a CXXFLAGS value.  */
 
 
static unsigned int
static unsigned int
ieee_vis_to_flags (enum debug_visibility visibility)
ieee_vis_to_flags (enum debug_visibility visibility)
{
{
  switch (visibility)
  switch (visibility)
    {
    {
    default:
    default:
      abort ();
      abort ();
    case DEBUG_VISIBILITY_PUBLIC:
    case DEBUG_VISIBILITY_PUBLIC:
      return CXXFLAGS_VISIBILITY_PUBLIC;
      return CXXFLAGS_VISIBILITY_PUBLIC;
    case DEBUG_VISIBILITY_PRIVATE:
    case DEBUG_VISIBILITY_PRIVATE:
      return CXXFLAGS_VISIBILITY_PRIVATE;
      return CXXFLAGS_VISIBILITY_PRIVATE;
    case DEBUG_VISIBILITY_PROTECTED:
    case DEBUG_VISIBILITY_PROTECTED:
      return CXXFLAGS_VISIBILITY_PROTECTED;
      return CXXFLAGS_VISIBILITY_PROTECTED;
    }
    }
  /*NOTREACHED*/
  /*NOTREACHED*/
}
}
 
 
/* Start defining a struct type.  We build it in the strdef field on
/* Start defining a struct type.  We build it in the strdef field on
   the stack, to avoid confusing type definitions required by the
   the stack, to avoid confusing type definitions required by the
   fields with the struct type itself.  */
   fields with the struct type itself.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_struct_type (void *p, const char *tag, unsigned int id,
ieee_start_struct_type (void *p, const char *tag, unsigned int id,
                        bfd_boolean structp, unsigned int size)
                        bfd_boolean structp, unsigned int size)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean localp, ignorep;
  bfd_boolean localp, ignorep;
  bfd_boolean copy;
  bfd_boolean copy;
  char ab[20];
  char ab[20];
  const char *look;
  const char *look;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type *nt, *ntlook;
  struct ieee_name_type *nt, *ntlook;
  struct ieee_buflist strdef;
  struct ieee_buflist strdef;
 
 
  localp = FALSE;
  localp = FALSE;
  ignorep = FALSE;
  ignorep = FALSE;
 
 
  /* We need to create a tag for internal use even if we don't want
  /* We need to create a tag for internal use even if we don't want
     one for external use.  This will let us refer to an anonymous
     one for external use.  This will let us refer to an anonymous
     struct.  */
     struct.  */
  if (tag != NULL)
  if (tag != NULL)
    {
    {
      look = tag;
      look = tag;
      copy = FALSE;
      copy = FALSE;
    }
    }
  else
  else
    {
    {
      sprintf (ab, "__anon%u", id);
      sprintf (ab, "__anon%u", id);
      look = ab;
      look = ab;
      copy = TRUE;
      copy = TRUE;
    }
    }
 
 
  /* If we already have references to the tag, we must use the
  /* If we already have references to the tag, we must use the
     existing type index.  */
     existing type index.  */
  h = ieee_name_type_hash_lookup (&info->tags, look, TRUE, copy);
  h = ieee_name_type_hash_lookup (&info->tags, look, TRUE, copy);
  if (h == NULL)
  if (h == NULL)
    return FALSE;
    return FALSE;
 
 
  nt = NULL;
  nt = NULL;
  for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
  for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
    {
    {
      if (ntlook->id == id)
      if (ntlook->id == id)
        nt = ntlook;
        nt = ntlook;
      else if (! ntlook->type.localp)
      else if (! ntlook->type.localp)
        {
        {
          /* We are creating a duplicate definition of a globally
          /* We are creating a duplicate definition of a globally
             defined tag.  Force it to be local to avoid
             defined tag.  Force it to be local to avoid
             confusion.  */
             confusion.  */
          localp = TRUE;
          localp = TRUE;
        }
        }
    }
    }
 
 
  if (nt != NULL)
  if (nt != NULL)
    {
    {
      assert (localp == nt->type.localp);
      assert (localp == nt->type.localp);
      if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
      if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
        {
        {
          /* We've already seen a global definition of the type.
          /* We've already seen a global definition of the type.
             Ignore this new definition.  */
             Ignore this new definition.  */
          ignorep = TRUE;
          ignorep = TRUE;
        }
        }
    }
    }
  else
  else
    {
    {
      nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
      nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
      memset (nt, 0, sizeof *nt);
      memset (nt, 0, sizeof *nt);
      nt->id = id;
      nt->id = id;
      nt->type.name = h->root.string;
      nt->type.name = h->root.string;
      nt->next = h->types;
      nt->next = h->types;
      h->types = nt;
      h->types = nt;
      nt->type.indx = info->type_indx;
      nt->type.indx = info->type_indx;
      ++info->type_indx;
      ++info->type_indx;
    }
    }
 
 
  nt->kind = DEBUG_KIND_ILLEGAL;
  nt->kind = DEBUG_KIND_ILLEGAL;
 
 
  if (! ieee_init_buffer (info, &strdef)
  if (! ieee_init_buffer (info, &strdef)
      || ! ieee_define_named_type (info, tag, nt->type.indx, size, TRUE,
      || ! ieee_define_named_type (info, tag, nt->type.indx, size, TRUE,
                                   localp, &strdef)
                                   localp, &strdef)
      || ! ieee_write_number (info, structp ? 'S' : 'U')
      || ! ieee_write_number (info, structp ? 'S' : 'U')
      || ! ieee_write_number (info, size))
      || ! ieee_write_number (info, size))
    return FALSE;
    return FALSE;
 
 
  if (! ignorep)
  if (! ignorep)
    {
    {
      const char *hold;
      const char *hold;
 
 
      /* We never want nt->type.name to be NULL.  We want the rest of
      /* We never want nt->type.name to be NULL.  We want the rest of
         the type to be the object set up on the type stack; it will
         the type to be the object set up on the type stack; it will
         have a NULL name if tag is NULL.  */
         have a NULL name if tag is NULL.  */
      hold = nt->type.name;
      hold = nt->type.name;
      nt->type = info->type_stack->type;
      nt->type = info->type_stack->type;
      nt->type.name = hold;
      nt->type.name = hold;
    }
    }
 
 
  info->type_stack->type.name = tag;
  info->type_stack->type.name = tag;
  info->type_stack->type.strdef = strdef;
  info->type_stack->type.strdef = strdef;
  info->type_stack->type.ignorep = ignorep;
  info->type_stack->type.ignorep = ignorep;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a field to a struct.  */
/* Add a field to a struct.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
ieee_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
                   enum debug_visibility visibility)
                   enum debug_visibility visibility)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int size;
  unsigned int size;
  bfd_boolean unsignedp;
  bfd_boolean unsignedp;
  bfd_boolean referencep;
  bfd_boolean referencep;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int indx;
  unsigned int indx;
  bfd_vma offset;
  bfd_vma offset;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->next != NULL
          && info->type_stack->next != NULL
          && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
          && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
 
 
  /* If we are ignoring this struct definition, just pop and ignore
  /* If we are ignoring this struct definition, just pop and ignore
     the type.  */
     the type.  */
  if (info->type_stack->next->type.ignorep)
  if (info->type_stack->next->type.ignorep)
    {
    {
      ieee_pop_unused_type (info);
      ieee_pop_unused_type (info);
      return TRUE;
      return TRUE;
    }
    }
 
 
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  unsignedp = info->type_stack->type.unsignedp;
  unsignedp = info->type_stack->type.unsignedp;
  referencep = info->type_stack->type.referencep;
  referencep = info->type_stack->type.referencep;
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  indx = ieee_pop_type (info);
  indx = ieee_pop_type (info);
 
 
  if (localp)
  if (localp)
    info->type_stack->type.localp = TRUE;
    info->type_stack->type.localp = TRUE;
 
 
  if (info->type_stack->type.classdef != NULL)
  if (info->type_stack->type.classdef != NULL)
    {
    {
      unsigned int flags;
      unsigned int flags;
      unsigned int nindx;
      unsigned int nindx;
 
 
      /* This is a class.  We must add a description of this field to
      /* This is a class.  We must add a description of this field to
         the class records we are building.  */
         the class records we are building.  */
 
 
      flags = ieee_vis_to_flags (visibility);
      flags = ieee_vis_to_flags (visibility);
      nindx = info->type_stack->type.classdef->indx;
      nindx = info->type_stack->type.classdef->indx;
      if (! ieee_change_buffer (info,
      if (! ieee_change_buffer (info,
                                &info->type_stack->type.classdef->pmiscbuf)
                                &info->type_stack->type.classdef->pmiscbuf)
          || ! ieee_write_asn (info, nindx, 'd')
          || ! ieee_write_asn (info, nindx, 'd')
          || ! ieee_write_asn (info, nindx, flags)
          || ! ieee_write_asn (info, nindx, flags)
          || ! ieee_write_atn65 (info, nindx, name)
          || ! ieee_write_atn65 (info, nindx, name)
          || ! ieee_write_atn65 (info, nindx, name))
          || ! ieee_write_atn65 (info, nindx, name))
        return FALSE;
        return FALSE;
      info->type_stack->type.classdef->pmisccount += 4;
      info->type_stack->type.classdef->pmisccount += 4;
 
 
      if (referencep)
      if (referencep)
        {
        {
          unsigned int nindx;
          unsigned int nindx;
 
 
          /* We need to output a record recording that this field is
          /* We need to output a record recording that this field is
             really of reference type.  We put this on the refs field
             really of reference type.  We put this on the refs field
             of classdef, so that it can be appended to the C++
             of classdef, so that it can be appended to the C++
             records after the class is defined.  */
             records after the class is defined.  */
 
 
          nindx = info->name_indx;
          nindx = info->name_indx;
          ++info->name_indx;
          ++info->name_indx;
 
 
          if (! ieee_change_buffer (info,
          if (! ieee_change_buffer (info,
                                    &info->type_stack->type.classdef->refs)
                                    &info->type_stack->type.classdef->refs)
              || ! ieee_write_byte (info, (int) ieee_nn_record)
              || ! ieee_write_byte (info, (int) ieee_nn_record)
              || ! ieee_write_number (info, nindx)
              || ! ieee_write_number (info, nindx)
              || ! ieee_write_id (info, "")
              || ! ieee_write_id (info, "")
              || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
              || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
              || ! ieee_write_number (info, nindx)
              || ! ieee_write_number (info, nindx)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 62)
              || ! ieee_write_number (info, 62)
              || ! ieee_write_number (info, 80)
              || ! ieee_write_number (info, 80)
              || ! ieee_write_number (info, 4)
              || ! ieee_write_number (info, 4)
              || ! ieee_write_asn (info, nindx, 'R')
              || ! ieee_write_asn (info, nindx, 'R')
              || ! ieee_write_asn (info, nindx, 3)
              || ! ieee_write_asn (info, nindx, 3)
              || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
              || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
              || ! ieee_write_atn65 (info, nindx, name))
              || ! ieee_write_atn65 (info, nindx, name))
            return FALSE;
            return FALSE;
        }
        }
    }
    }
 
 
  /* If the bitsize doesn't match the expected size, we need to output
  /* If the bitsize doesn't match the expected size, we need to output
     a bitfield type.  */
     a bitfield type.  */
  if (size == 0 || bitsize == 0 || bitsize == size * 8)
  if (size == 0 || bitsize == 0 || bitsize == size * 8)
    offset = bitpos / 8;
    offset = bitpos / 8;
  else
  else
    {
    {
      if (! ieee_define_type (info, 0, unsignedp,
      if (! ieee_define_type (info, 0, unsignedp,
                              info->type_stack->type.localp)
                              info->type_stack->type.localp)
          || ! ieee_write_number (info, 'g')
          || ! ieee_write_number (info, 'g')
          || ! ieee_write_number (info, unsignedp ? 0 : 1)
          || ! ieee_write_number (info, unsignedp ? 0 : 1)
          || ! ieee_write_number (info, bitsize)
          || ! ieee_write_number (info, bitsize)
          || ! ieee_write_number (info, indx))
          || ! ieee_write_number (info, indx))
        return FALSE;
        return FALSE;
      indx = ieee_pop_type (info);
      indx = ieee_pop_type (info);
      offset = bitpos;
      offset = bitpos;
    }
    }
 
 
  /* Switch to the struct we are building in order to output this
  /* Switch to the struct we are building in order to output this
     field definition.  */
     field definition.  */
  return (ieee_change_buffer (info, &info->type_stack->type.strdef)
  return (ieee_change_buffer (info, &info->type_stack->type.strdef)
          && ieee_write_id (info, name)
          && ieee_write_id (info, name)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, indx)
          && ieee_write_number (info, offset));
          && ieee_write_number (info, offset));
}
}
 
 
/* Finish up a struct type.  */
/* Finish up a struct type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_end_struct_type (void *p)
ieee_end_struct_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_buflist *pb;
  struct ieee_buflist *pb;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
          && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
 
 
  /* If we were ignoring this struct definition because it was a
  /* If we were ignoring this struct definition because it was a
     duplicate definition, just through away whatever bytes we have
     duplicate definition, just through away whatever bytes we have
     accumulated.  Leave the type on the stack.  */
     accumulated.  Leave the type on the stack.  */
  if (info->type_stack->type.ignorep)
  if (info->type_stack->type.ignorep)
    return TRUE;
    return TRUE;
 
 
  /* If this is not a duplicate definition of this tag, then localp
  /* If this is not a duplicate definition of this tag, then localp
     will be FALSE, and we can put it in the global type block.
     will be FALSE, and we can put it in the global type block.
     FIXME: We should avoid outputting duplicate definitions which are
     FIXME: We should avoid outputting duplicate definitions which are
     the same.  */
     the same.  */
  if (! info->type_stack->type.localp)
  if (! info->type_stack->type.localp)
    {
    {
      /* Make sure we have started the global type block.  */
      /* Make sure we have started the global type block.  */
      if (ieee_buffer_emptyp (&info->global_types))
      if (ieee_buffer_emptyp (&info->global_types))
        {
        {
          if (! ieee_change_buffer (info, &info->global_types)
          if (! ieee_change_buffer (info, &info->global_types)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_byte (info, 2)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, ""))
              || ! ieee_write_id (info, ""))
            return FALSE;
            return FALSE;
        }
        }
      pb = &info->global_types;
      pb = &info->global_types;
    }
    }
  else
  else
    {
    {
      /* Make sure we have started the types block.  */
      /* Make sure we have started the types block.  */
      if (ieee_buffer_emptyp (&info->types))
      if (ieee_buffer_emptyp (&info->types))
        {
        {
          if (! ieee_change_buffer (info, &info->types)
          if (! ieee_change_buffer (info, &info->types)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 1)
              || ! ieee_write_byte (info, 1)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, info->modname))
              || ! ieee_write_id (info, info->modname))
            return FALSE;
            return FALSE;
        }
        }
      pb = &info->types;
      pb = &info->types;
    }
    }
 
 
  /* Append the struct definition to the types.  */
  /* Append the struct definition to the types.  */
  if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
  if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
      || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
      || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
    return FALSE;
    return FALSE;
 
 
  /* Leave the struct on the type stack.  */
  /* Leave the struct on the type stack.  */
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a class type.  */
/* Start a class type.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_class_type (void *p, const char *tag, unsigned int id,
ieee_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 ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  const char *vclass;
  const char *vclass;
  struct ieee_buflist pmiscbuf;
  struct ieee_buflist pmiscbuf;
  unsigned int indx;
  unsigned int indx;
  struct ieee_type_class *classdef;
  struct ieee_type_class *classdef;
 
 
  /* A C++ class is output as a C++ struct along with a set of pmisc
  /* A C++ class is output as a C++ struct along with a set of pmisc
     records describing the class.  */
     records describing the class.  */
 
 
  /* We need to have a name so that we can associate the struct and
  /* We need to have a name so that we can associate the struct and
     the class.  */
     the class.  */
  if (tag == NULL)
  if (tag == NULL)
    {
    {
      char *t;
      char *t;
 
 
      t = (char *) xmalloc (20);
      t = (char *) xmalloc (20);
      sprintf (t, "__anon%u", id);
      sprintf (t, "__anon%u", id);
      tag = t;
      tag = t;
    }
    }
 
 
  /* We can't write out the virtual table information until we have
  /* We can't write out the virtual table information until we have
     finished the class, because we don't know the virtual table size.
     finished the class, because we don't know the virtual table size.
     We get the size from the largest voffset we see.  */
     We get the size from the largest voffset we see.  */
  vclass = NULL;
  vclass = NULL;
  if (vptr && ! ownvptr)
  if (vptr && ! ownvptr)
    {
    {
      vclass = info->type_stack->type.name;
      vclass = info->type_stack->type.name;
      assert (vclass != NULL);
      assert (vclass != NULL);
      /* We don't call ieee_pop_unused_type, since the class should
      /* We don't call ieee_pop_unused_type, since the class should
         get defined.  */
         get defined.  */
      (void) ieee_pop_type (info);
      (void) ieee_pop_type (info);
    }
    }
 
 
  if (! ieee_start_struct_type (p, tag, id, structp, size))
  if (! ieee_start_struct_type (p, tag, id, structp, size))
    return FALSE;
    return FALSE;
 
 
  indx = info->name_indx;
  indx = info->name_indx;
  ++info->name_indx;
  ++info->name_indx;
 
 
  /* We write out pmisc records into the classdef field.  We will
  /* We write out pmisc records into the classdef field.  We will
     write out the pmisc start after we know the number of records we
     write out the pmisc start after we know the number of records we
     need.  */
     need.  */
  if (! ieee_init_buffer (info, &pmiscbuf)
  if (! ieee_init_buffer (info, &pmiscbuf)
      || ! ieee_change_buffer (info, &pmiscbuf)
      || ! ieee_change_buffer (info, &pmiscbuf)
      || ! ieee_write_asn (info, indx, 'T')
      || ! ieee_write_asn (info, indx, 'T')
      || ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
      || ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
      || ! ieee_write_atn65 (info, indx, tag))
      || ! ieee_write_atn65 (info, indx, tag))
    return FALSE;
    return FALSE;
 
 
  classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
  classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
  memset (classdef, 0, sizeof *classdef);
  memset (classdef, 0, sizeof *classdef);
 
 
  classdef->indx = indx;
  classdef->indx = indx;
  classdef->pmiscbuf = pmiscbuf;
  classdef->pmiscbuf = pmiscbuf;
  classdef->pmisccount = 3;
  classdef->pmisccount = 3;
  classdef->vclass = vclass;
  classdef->vclass = vclass;
  classdef->ownvptr = ownvptr;
  classdef->ownvptr = ownvptr;
 
 
  info->type_stack->type.classdef = classdef;
  info->type_stack->type.classdef = classdef;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a static member to a class.  */
/* Add a static member to a class.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_static_member (void *p, const char *name, const char *physname,
ieee_class_static_member (void *p, const char *name, const char *physname,
                          enum debug_visibility visibility)
                          enum debug_visibility visibility)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int flags;
  unsigned int flags;
  unsigned int nindx;
  unsigned int nindx;
 
 
  /* We don't care about the type.  Hopefully there will be a call to
  /* We don't care about the type.  Hopefully there will be a call to
     ieee_variable declaring the physical name and the type, since
     ieee_variable declaring the physical name and the type, since
     that is where an IEEE consumer must get the type.  */
     that is where an IEEE consumer must get the type.  */
  ieee_pop_unused_type (info);
  ieee_pop_unused_type (info);
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.classdef != NULL);
          && info->type_stack->type.classdef != NULL);
 
 
  flags = ieee_vis_to_flags (visibility);
  flags = ieee_vis_to_flags (visibility);
  flags |= CXXFLAGS_STATIC;
  flags |= CXXFLAGS_STATIC;
 
 
  nindx = info->type_stack->type.classdef->indx;
  nindx = info->type_stack->type.classdef->indx;
 
 
  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
      || ! ieee_write_asn (info, nindx, 'd')
      || ! ieee_write_asn (info, nindx, 'd')
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_atn65 (info, nindx, name)
      || ! ieee_write_atn65 (info, nindx, name)
      || ! ieee_write_atn65 (info, nindx, physname))
      || ! ieee_write_atn65 (info, nindx, physname))
    return FALSE;
    return FALSE;
  info->type_stack->type.classdef->pmisccount += 4;
  info->type_stack->type.classdef->pmisccount += 4;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a base class to a class.  */
/* Add a base class to a class.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
ieee_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
                      enum debug_visibility visibility)
                      enum debug_visibility visibility)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  const char *bname;
  const char *bname;
  bfd_boolean localp;
  bfd_boolean localp;
  unsigned int bindx;
  unsigned int bindx;
  char *fname;
  char *fname;
  unsigned int flags;
  unsigned int flags;
  unsigned int nindx;
  unsigned int nindx;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.name != NULL
          && info->type_stack->type.name != NULL
          && info->type_stack->next != NULL
          && info->type_stack->next != NULL
          && info->type_stack->next->type.classdef != NULL
          && info->type_stack->next->type.classdef != NULL
          && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
          && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
 
 
  bname = info->type_stack->type.name;
  bname = info->type_stack->type.name;
  localp = info->type_stack->type.localp;
  localp = info->type_stack->type.localp;
  bindx = ieee_pop_type (info);
  bindx = ieee_pop_type (info);
 
 
  /* We are currently defining both a struct and a class.  We must
  /* We are currently defining both a struct and a class.  We must
     write out a field definition in the struct which holds the base
     write out a field definition in the struct which holds the base
     class.  The stabs debugging reader will create a field named
     class.  The stabs debugging reader will create a field named
     _vb$CLASS for a virtual base class, so we just use that.  FIXME:
     _vb$CLASS for a virtual base class, so we just use that.  FIXME:
     we should not depend upon a detail of stabs debugging.  */
     we should not depend upon a detail of stabs debugging.  */
  if (virtual)
  if (virtual)
    {
    {
      fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
      fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
      sprintf (fname, "_vb$%s", bname);
      sprintf (fname, "_vb$%s", bname);
      flags = BASEFLAGS_VIRTUAL;
      flags = BASEFLAGS_VIRTUAL;
    }
    }
  else
  else
    {
    {
      if (localp)
      if (localp)
        info->type_stack->type.localp = TRUE;
        info->type_stack->type.localp = TRUE;
 
 
      fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
      fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
      sprintf (fname, "_b$%s", bname);
      sprintf (fname, "_b$%s", bname);
 
 
      if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
      if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
          || ! ieee_write_id (info, fname)
          || ! ieee_write_id (info, fname)
          || ! ieee_write_number (info, bindx)
          || ! ieee_write_number (info, bindx)
          || ! ieee_write_number (info, bitpos / 8))
          || ! ieee_write_number (info, bitpos / 8))
        return FALSE;
        return FALSE;
      flags = 0;
      flags = 0;
    }
    }
 
 
  if (visibility == DEBUG_VISIBILITY_PRIVATE)
  if (visibility == DEBUG_VISIBILITY_PRIVATE)
    flags |= BASEFLAGS_PRIVATE;
    flags |= BASEFLAGS_PRIVATE;
 
 
  nindx = info->type_stack->type.classdef->indx;
  nindx = info->type_stack->type.classdef->indx;
 
 
  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
      || ! ieee_write_asn (info, nindx, 'b')
      || ! ieee_write_asn (info, nindx, 'b')
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_atn65 (info, nindx, bname)
      || ! ieee_write_atn65 (info, nindx, bname)
      || ! ieee_write_asn (info, nindx, 0)
      || ! ieee_write_asn (info, nindx, 0)
      || ! ieee_write_atn65 (info, nindx, fname))
      || ! ieee_write_atn65 (info, nindx, fname))
    return FALSE;
    return FALSE;
  info->type_stack->type.classdef->pmisccount += 5;
  info->type_stack->type.classdef->pmisccount += 5;
 
 
  free (fname);
  free (fname);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start building a method for a class.  */
/* Start building a method for a class.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_start_method (void *p, const char *name)
ieee_class_start_method (void *p, const char *name)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef->method == NULL);
          && info->type_stack->type.classdef->method == NULL);
 
 
  info->type_stack->type.classdef->method = name;
  info->type_stack->type.classdef->method = name;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Define a new method variant, either static or not.  */
/* Define a new method variant, either static or not.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_method_var (struct ieee_handle *info, const char *physname,
ieee_class_method_var (struct ieee_handle *info, const char *physname,
                       enum debug_visibility visibility,
                       enum debug_visibility visibility,
                       bfd_boolean staticp, bfd_boolean constp,
                       bfd_boolean staticp, bfd_boolean constp,
                       bfd_boolean volatilep, bfd_vma voffset,
                       bfd_boolean volatilep, bfd_vma voffset,
                       bfd_boolean context)
                       bfd_boolean context)
{
{
  unsigned int flags;
  unsigned int flags;
  unsigned int nindx;
  unsigned int nindx;
  bfd_boolean virtual;
  bfd_boolean virtual;
 
 
  /* We don't need the type of the method.  An IEEE consumer which
  /* We don't need the type of the method.  An IEEE consumer which
     wants the type must track down the function by the physical name
     wants the type must track down the function by the physical name
     and get the type from that.  */
     and get the type from that.  */
  ieee_pop_unused_type (info);
  ieee_pop_unused_type (info);
 
 
  /* We don't use the context.  FIXME: We probably ought to use it to
  /* We don't use the context.  FIXME: We probably ought to use it to
     adjust the voffset somehow, but I don't really know how.  */
     adjust the voffset somehow, but I don't really know how.  */
  if (context)
  if (context)
    ieee_pop_unused_type (info);
    ieee_pop_unused_type (info);
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef->method != NULL);
          && info->type_stack->type.classdef->method != NULL);
 
 
  flags = ieee_vis_to_flags (visibility);
  flags = ieee_vis_to_flags (visibility);
 
 
  /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
  /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
     CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE.  */
     CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE.  */
 
 
  if (staticp)
  if (staticp)
    flags |= CXXFLAGS_STATIC;
    flags |= CXXFLAGS_STATIC;
  if (constp)
  if (constp)
    flags |= CXXFLAGS_CONST;
    flags |= CXXFLAGS_CONST;
  if (volatilep)
  if (volatilep)
    flags |= CXXFLAGS_VOLATILE;
    flags |= CXXFLAGS_VOLATILE;
 
 
  nindx = info->type_stack->type.classdef->indx;
  nindx = info->type_stack->type.classdef->indx;
 
 
  virtual = context || voffset > 0;
  virtual = context || voffset > 0;
 
 
  if (! ieee_change_buffer (info,
  if (! ieee_change_buffer (info,
                            &info->type_stack->type.classdef->pmiscbuf)
                            &info->type_stack->type.classdef->pmiscbuf)
      || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
      || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_asn (info, nindx, flags)
      || ! ieee_write_atn65 (info, nindx,
      || ! ieee_write_atn65 (info, nindx,
                             info->type_stack->type.classdef->method)
                             info->type_stack->type.classdef->method)
      || ! ieee_write_atn65 (info, nindx, physname))
      || ! ieee_write_atn65 (info, nindx, physname))
    return FALSE;
    return FALSE;
 
 
  if (virtual)
  if (virtual)
    {
    {
      if (voffset > info->type_stack->type.classdef->voffset)
      if (voffset > info->type_stack->type.classdef->voffset)
        info->type_stack->type.classdef->voffset = voffset;
        info->type_stack->type.classdef->voffset = voffset;
      if (! ieee_write_asn (info, nindx, voffset))
      if (! ieee_write_asn (info, nindx, voffset))
        return FALSE;
        return FALSE;
      ++info->type_stack->type.classdef->pmisccount;
      ++info->type_stack->type.classdef->pmisccount;
    }
    }
 
 
  if (! ieee_write_asn (info, nindx, 0))
  if (! ieee_write_asn (info, nindx, 0))
    return FALSE;
    return FALSE;
 
 
  info->type_stack->type.classdef->pmisccount += 5;
  info->type_stack->type.classdef->pmisccount += 5;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Define a new method variant.  */
/* Define a new method variant.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_method_variant (void *p, const char *physname,
ieee_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 ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  return ieee_class_method_var (info, physname, visibility, FALSE, constp,
  return ieee_class_method_var (info, physname, visibility, FALSE, constp,
                                volatilep, voffset, context);
                                volatilep, voffset, context);
}
}
 
 
/* Define a new static method variant.  */
/* Define a new static method variant.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_static_method_variant (void *p, const char *physname,
ieee_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 ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  return ieee_class_method_var (info, physname, visibility, TRUE, constp,
  return ieee_class_method_var (info, physname, visibility, TRUE, constp,
                                volatilep, 0, FALSE);
                                volatilep, 0, FALSE);
}
}
 
 
/* Finish up a method.  */
/* Finish up a method.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_class_end_method (void *p)
ieee_class_end_method (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef != NULL
          && info->type_stack->type.classdef->method != NULL);
          && info->type_stack->type.classdef->method != NULL);
 
 
  info->type_stack->type.classdef->method = NULL;
  info->type_stack->type.classdef->method = NULL;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Finish up a class.  */
/* Finish up a class.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_end_class_type (void *p)
ieee_end_class_type (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int nindx;
  unsigned int nindx;
 
 
  assert (info->type_stack != NULL
  assert (info->type_stack != NULL
          && info->type_stack->type.classdef != NULL);
          && info->type_stack->type.classdef != NULL);
 
 
  /* If we were ignoring this class definition because it was a
  /* If we were ignoring this class definition because it was a
     duplicate definition, just through away whatever bytes we have
     duplicate definition, just through away whatever bytes we have
     accumulated.  Leave the type on the stack.  */
     accumulated.  Leave the type on the stack.  */
  if (info->type_stack->type.ignorep)
  if (info->type_stack->type.ignorep)
    return TRUE;
    return TRUE;
 
 
  nindx = info->type_stack->type.classdef->indx;
  nindx = info->type_stack->type.classdef->indx;
 
 
  /* If we have a virtual table, we can write out the information now.  */
  /* If we have a virtual table, we can write out the information now.  */
  if (info->type_stack->type.classdef->vclass != NULL
  if (info->type_stack->type.classdef->vclass != NULL
      || info->type_stack->type.classdef->ownvptr)
      || info->type_stack->type.classdef->ownvptr)
    {
    {
      if (! ieee_change_buffer (info,
      if (! ieee_change_buffer (info,
                                &info->type_stack->type.classdef->pmiscbuf)
                                &info->type_stack->type.classdef->pmiscbuf)
          || ! ieee_write_asn (info, nindx, 'z')
          || ! ieee_write_asn (info, nindx, 'z')
          || ! ieee_write_atn65 (info, nindx, "")
          || ! ieee_write_atn65 (info, nindx, "")
          || ! ieee_write_asn (info, nindx,
          || ! ieee_write_asn (info, nindx,
                               info->type_stack->type.classdef->voffset))
                               info->type_stack->type.classdef->voffset))
        return FALSE;
        return FALSE;
      if (info->type_stack->type.classdef->ownvptr)
      if (info->type_stack->type.classdef->ownvptr)
        {
        {
          if (! ieee_write_atn65 (info, nindx, ""))
          if (! ieee_write_atn65 (info, nindx, ""))
            return FALSE;
            return FALSE;
        }
        }
      else
      else
        {
        {
          if (! ieee_write_atn65 (info, nindx,
          if (! ieee_write_atn65 (info, nindx,
                                  info->type_stack->type.classdef->vclass))
                                  info->type_stack->type.classdef->vclass))
            return FALSE;
            return FALSE;
        }
        }
      if (! ieee_write_asn (info, nindx, 0))
      if (! ieee_write_asn (info, nindx, 0))
        return FALSE;
        return FALSE;
      info->type_stack->type.classdef->pmisccount += 5;
      info->type_stack->type.classdef->pmisccount += 5;
    }
    }
 
 
  /* Now that we know the number of pmisc records, we can write out
  /* Now that we know the number of pmisc records, we can write out
     the atn62 which starts the pmisc records, and append them to the
     the atn62 which starts the pmisc records, and append them to the
     C++ buffers.  */
     C++ buffers.  */
 
 
  if (! ieee_change_buffer (info, &info->cxx)
  if (! ieee_change_buffer (info, &info->cxx)
      || ! ieee_write_byte (info, (int) ieee_nn_record)
      || ! ieee_write_byte (info, (int) ieee_nn_record)
      || ! ieee_write_number (info, nindx)
      || ! ieee_write_number (info, nindx)
      || ! ieee_write_id (info, "")
      || ! ieee_write_id (info, "")
      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
      || ! ieee_write_number (info, nindx)
      || ! ieee_write_number (info, nindx)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 62)
      || ! ieee_write_number (info, 62)
      || ! ieee_write_number (info, 80)
      || ! ieee_write_number (info, 80)
      || ! ieee_write_number (info,
      || ! ieee_write_number (info,
                              info->type_stack->type.classdef->pmisccount))
                              info->type_stack->type.classdef->pmisccount))
    return FALSE;
    return FALSE;
 
 
  if (! ieee_append_buffer (info, &info->cxx,
  if (! ieee_append_buffer (info, &info->cxx,
                            &info->type_stack->type.classdef->pmiscbuf))
                            &info->type_stack->type.classdef->pmiscbuf))
    return FALSE;
    return FALSE;
  if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
  if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
    {
    {
      if (! ieee_append_buffer (info, &info->cxx,
      if (! ieee_append_buffer (info, &info->cxx,
                                &info->type_stack->type.classdef->refs))
                                &info->type_stack->type.classdef->refs))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return ieee_end_struct_type (p);
  return ieee_end_struct_type (p);
}
}
 
 
/* Push a previously seen typedef onto the type stack.  */
/* Push a previously seen typedef onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_typedef_type (void *p, const char *name)
ieee_typedef_type (void *p, const char *name)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type *nt;
  struct ieee_name_type *nt;
 
 
  h = ieee_name_type_hash_lookup (&info->typedefs, name, FALSE, FALSE);
  h = ieee_name_type_hash_lookup (&info->typedefs, name, FALSE, FALSE);
 
 
  /* h should never be NULL, since that would imply that the generic
  /* h should never be NULL, since that would imply that the generic
     debugging code has asked for a typedef which it has not yet
     debugging code has asked for a typedef which it has not yet
     defined.  */
     defined.  */
  assert (h != NULL);
  assert (h != NULL);
 
 
  /* We always use the most recently defined type for this name, which
  /* We always use the most recently defined type for this name, which
     will be the first one on the list.  */
     will be the first one on the list.  */
 
 
  nt = h->types;
  nt = h->types;
  if (! ieee_push_type (info, nt->type.indx, nt->type.size,
  if (! ieee_push_type (info, nt->type.indx, nt->type.size,
                        nt->type.unsignedp, nt->type.localp))
                        nt->type.unsignedp, nt->type.localp))
    return FALSE;
    return FALSE;
 
 
  /* Copy over any other type information we may have.  */
  /* Copy over any other type information we may have.  */
  info->type_stack->type = nt->type;
  info->type_stack->type = nt->type;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Push a tagged type onto the type stack.  */
/* Push a tagged type onto the type stack.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_tag_type (void *p, const char *name, unsigned int id,
ieee_tag_type (void *p, const char *name, unsigned int id,
               enum debug_type_kind kind)
               enum debug_type_kind kind)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean localp;
  bfd_boolean localp;
  bfd_boolean copy;
  bfd_boolean copy;
  char ab[20];
  char ab[20];
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type *nt;
  struct ieee_name_type *nt;
 
 
  if (kind == DEBUG_KIND_ENUM)
  if (kind == DEBUG_KIND_ENUM)
    {
    {
      struct ieee_defined_enum *e;
      struct ieee_defined_enum *e;
 
 
      if (name == NULL)
      if (name == NULL)
        abort ();
        abort ();
      for (e = info->enums; e != NULL; e = e->next)
      for (e = info->enums; e != NULL; e = e->next)
        if (e->tag != NULL && strcmp (e->tag, name) == 0)
        if (e->tag != NULL && strcmp (e->tag, name) == 0)
          return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
          return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
 
 
      e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
      e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
      memset (e, 0, sizeof *e);
      memset (e, 0, sizeof *e);
 
 
      e->indx = info->type_indx;
      e->indx = info->type_indx;
      ++info->type_indx;
      ++info->type_indx;
      e->tag = name;
      e->tag = name;
      e->defined = FALSE;
      e->defined = FALSE;
 
 
      e->next = info->enums;
      e->next = info->enums;
      info->enums = e;
      info->enums = e;
 
 
      return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
      return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
    }
    }
 
 
  localp = FALSE;
  localp = FALSE;
 
 
  copy = FALSE;
  copy = FALSE;
  if (name == NULL)
  if (name == NULL)
    {
    {
      sprintf (ab, "__anon%u", id);
      sprintf (ab, "__anon%u", id);
      name = ab;
      name = ab;
      copy = TRUE;
      copy = TRUE;
    }
    }
 
 
  h = ieee_name_type_hash_lookup (&info->tags, name, TRUE, copy);
  h = ieee_name_type_hash_lookup (&info->tags, name, TRUE, copy);
  if (h == NULL)
  if (h == NULL)
    return FALSE;
    return FALSE;
 
 
  for (nt = h->types; nt != NULL; nt = nt->next)
  for (nt = h->types; nt != NULL; nt = nt->next)
    {
    {
      if (nt->id == id)
      if (nt->id == id)
        {
        {
          if (! ieee_push_type (info, nt->type.indx, nt->type.size,
          if (! ieee_push_type (info, nt->type.indx, nt->type.size,
                                nt->type.unsignedp, nt->type.localp))
                                nt->type.unsignedp, nt->type.localp))
            return FALSE;
            return FALSE;
          /* Copy over any other type information we may have.  */
          /* Copy over any other type information we may have.  */
          info->type_stack->type = nt->type;
          info->type_stack->type = nt->type;
          return TRUE;
          return TRUE;
        }
        }
 
 
      if (! nt->type.localp)
      if (! nt->type.localp)
        {
        {
          /* This is a duplicate of a global type, so it must be
          /* This is a duplicate of a global type, so it must be
             local.  */
             local.  */
          localp = TRUE;
          localp = TRUE;
        }
        }
    }
    }
 
 
  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
  memset (nt, 0, sizeof *nt);
  memset (nt, 0, sizeof *nt);
 
 
  nt->id = id;
  nt->id = id;
  nt->type.name = h->root.string;
  nt->type.name = h->root.string;
  nt->type.indx = info->type_indx;
  nt->type.indx = info->type_indx;
  nt->type.localp = localp;
  nt->type.localp = localp;
  ++info->type_indx;
  ++info->type_indx;
  nt->kind = kind;
  nt->kind = kind;
 
 
  nt->next = h->types;
  nt->next = h->types;
  h->types = nt;
  h->types = nt;
 
 
  if (! ieee_push_type (info, nt->type.indx, 0, FALSE, localp))
  if (! ieee_push_type (info, nt->type.indx, 0, FALSE, localp))
    return FALSE;
    return FALSE;
 
 
  info->type_stack->type.name = h->root.string;
  info->type_stack->type.name = h->root.string;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typedef.  */
/* Output a typedef.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_typdef (void *p, const char *name)
ieee_typdef (void *p, const char *name)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_write_type type;
  struct ieee_write_type type;
  unsigned int indx;
  unsigned int indx;
  bfd_boolean found;
  bfd_boolean found;
  bfd_boolean localp;
  bfd_boolean localp;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type_hash_entry *h;
  struct ieee_name_type *nt;
  struct ieee_name_type *nt;
 
 
  type = info->type_stack->type;
  type = info->type_stack->type;
  indx = type.indx;
  indx = type.indx;
 
 
  /* If this is a simple builtin type using a builtin name, we don't
  /* If this is a simple builtin type using a builtin name, we don't
     want to output the typedef itself.  We also want to change the
     want to output the typedef itself.  We also want to change the
     type index to correspond to the name being used.  We recognize
     type index to correspond to the name being used.  We recognize
     names used in stabs debugging output even if they don't exactly
     names used in stabs debugging output even if they don't exactly
     correspond to the names used for the IEEE builtin types.  */
     correspond to the names used for the IEEE builtin types.  */
  found = FALSE;
  found = FALSE;
  if (indx <= (unsigned int) builtin_bcd_float)
  if (indx <= (unsigned int) builtin_bcd_float)
    {
    {
      switch ((enum builtin_types) indx)
      switch ((enum builtin_types) indx)
        {
        {
        default:
        default:
          break;
          break;
 
 
        case builtin_void:
        case builtin_void:
          if (strcmp (name, "void") == 0)
          if (strcmp (name, "void") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_signed_char:
        case builtin_signed_char:
        case builtin_char:
        case builtin_char:
          if (strcmp (name, "signed char") == 0)
          if (strcmp (name, "signed char") == 0)
            {
            {
              indx = (unsigned int) builtin_signed_char;
              indx = (unsigned int) builtin_signed_char;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "char") == 0)
          else if (strcmp (name, "char") == 0)
            {
            {
              indx = (unsigned int) builtin_char;
              indx = (unsigned int) builtin_char;
              found = TRUE;
              found = TRUE;
            }
            }
          break;
          break;
 
 
        case builtin_unsigned_char:
        case builtin_unsigned_char:
          if (strcmp (name, "unsigned char") == 0)
          if (strcmp (name, "unsigned char") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_signed_short_int:
        case builtin_signed_short_int:
        case builtin_short:
        case builtin_short:
        case builtin_short_int:
        case builtin_short_int:
        case builtin_signed_short:
        case builtin_signed_short:
          if (strcmp (name, "signed short int") == 0)
          if (strcmp (name, "signed short int") == 0)
            {
            {
              indx = (unsigned int) builtin_signed_short_int;
              indx = (unsigned int) builtin_signed_short_int;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "short") == 0)
          else if (strcmp (name, "short") == 0)
            {
            {
              indx = (unsigned int) builtin_short;
              indx = (unsigned int) builtin_short;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "short int") == 0)
          else if (strcmp (name, "short int") == 0)
            {
            {
              indx = (unsigned int) builtin_short_int;
              indx = (unsigned int) builtin_short_int;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "signed short") == 0)
          else if (strcmp (name, "signed short") == 0)
            {
            {
              indx = (unsigned int) builtin_signed_short;
              indx = (unsigned int) builtin_signed_short;
              found = TRUE;
              found = TRUE;
            }
            }
          break;
          break;
 
 
        case builtin_unsigned_short_int:
        case builtin_unsigned_short_int:
        case builtin_unsigned_short:
        case builtin_unsigned_short:
          if (strcmp (name, "unsigned short int") == 0
          if (strcmp (name, "unsigned short int") == 0
              || strcmp (name, "short unsigned int") == 0)
              || strcmp (name, "short unsigned int") == 0)
            {
            {
              indx = builtin_unsigned_short_int;
              indx = builtin_unsigned_short_int;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "unsigned short") == 0)
          else if (strcmp (name, "unsigned short") == 0)
            {
            {
              indx = builtin_unsigned_short;
              indx = builtin_unsigned_short;
              found = TRUE;
              found = TRUE;
            }
            }
          break;
          break;
 
 
        case builtin_signed_long:
        case builtin_signed_long:
        case builtin_int: /* FIXME: Size depends upon architecture.  */
        case builtin_int: /* FIXME: Size depends upon architecture.  */
        case builtin_long:
        case builtin_long:
          if (strcmp (name, "signed long") == 0)
          if (strcmp (name, "signed long") == 0)
            {
            {
              indx = builtin_signed_long;
              indx = builtin_signed_long;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "int") == 0)
          else if (strcmp (name, "int") == 0)
            {
            {
              indx = builtin_int;
              indx = builtin_int;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "long") == 0
          else if (strcmp (name, "long") == 0
                   || strcmp (name, "long int") == 0)
                   || strcmp (name, "long int") == 0)
            {
            {
              indx = builtin_long;
              indx = builtin_long;
              found = TRUE;
              found = TRUE;
            }
            }
          break;
          break;
 
 
        case builtin_unsigned_long:
        case builtin_unsigned_long:
        case builtin_unsigned: /* FIXME: Size depends upon architecture.  */
        case builtin_unsigned: /* FIXME: Size depends upon architecture.  */
        case builtin_unsigned_int: /* FIXME: Like builtin_unsigned.  */
        case builtin_unsigned_int: /* FIXME: Like builtin_unsigned.  */
          if (strcmp (name, "unsigned long") == 0
          if (strcmp (name, "unsigned long") == 0
              || strcmp (name, "long unsigned int") == 0)
              || strcmp (name, "long unsigned int") == 0)
            {
            {
              indx = builtin_unsigned_long;
              indx = builtin_unsigned_long;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "unsigned") == 0)
          else if (strcmp (name, "unsigned") == 0)
            {
            {
              indx = builtin_unsigned;
              indx = builtin_unsigned;
              found = TRUE;
              found = TRUE;
            }
            }
          else if (strcmp (name, "unsigned int") == 0)
          else if (strcmp (name, "unsigned int") == 0)
            {
            {
              indx = builtin_unsigned_int;
              indx = builtin_unsigned_int;
              found = TRUE;
              found = TRUE;
            }
            }
          break;
          break;
 
 
        case builtin_signed_long_long:
        case builtin_signed_long_long:
          if (strcmp (name, "signed long long") == 0
          if (strcmp (name, "signed long long") == 0
              || strcmp (name, "long long int") == 0)
              || strcmp (name, "long long int") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_unsigned_long_long:
        case builtin_unsigned_long_long:
          if (strcmp (name, "unsigned long long") == 0
          if (strcmp (name, "unsigned long long") == 0
              || strcmp (name, "long long unsigned int") == 0)
              || strcmp (name, "long long unsigned int") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_float:
        case builtin_float:
          if (strcmp (name, "float") == 0)
          if (strcmp (name, "float") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_double:
        case builtin_double:
          if (strcmp (name, "double") == 0)
          if (strcmp (name, "double") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_long_double:
        case builtin_long_double:
          if (strcmp (name, "long double") == 0)
          if (strcmp (name, "long double") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
 
 
        case builtin_long_long_double:
        case builtin_long_long_double:
          if (strcmp (name, "long long double") == 0)
          if (strcmp (name, "long long double") == 0)
            found = TRUE;
            found = TRUE;
          break;
          break;
        }
        }
 
 
      if (found)
      if (found)
        type.indx = indx;
        type.indx = indx;
    }
    }
 
 
  h = ieee_name_type_hash_lookup (&info->typedefs, name, TRUE, FALSE);
  h = ieee_name_type_hash_lookup (&info->typedefs, name, TRUE, FALSE);
  if (h == NULL)
  if (h == NULL)
    return FALSE;
    return FALSE;
 
 
  /* See if we have already defined this type with this name.  */
  /* See if we have already defined this type with this name.  */
  localp = type.localp;
  localp = type.localp;
  for (nt = h->types; nt != NULL; nt = nt->next)
  for (nt = h->types; nt != NULL; nt = nt->next)
    {
    {
      if (nt->id == indx)
      if (nt->id == indx)
        {
        {
          /* If this is a global definition, then we don't need to
          /* If this is a global definition, then we don't need to
             do anything here.  */
             do anything here.  */
          if (! nt->type.localp)
          if (! nt->type.localp)
            {
            {
              ieee_pop_unused_type (info);
              ieee_pop_unused_type (info);
              return TRUE;
              return TRUE;
            }
            }
        }
        }
      else
      else
        {
        {
          /* This is a duplicate definition, so make this one local.  */
          /* This is a duplicate definition, so make this one local.  */
          localp = TRUE;
          localp = TRUE;
        }
        }
    }
    }
 
 
  /* We need to add a new typedef for this type.  */
  /* We need to add a new typedef for this type.  */
 
 
  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
  memset (nt, 0, sizeof *nt);
  memset (nt, 0, sizeof *nt);
  nt->id = indx;
  nt->id = indx;
  nt->type = type;
  nt->type = type;
  nt->type.name = name;
  nt->type.name = name;
  nt->type.localp = localp;
  nt->type.localp = localp;
  nt->kind = DEBUG_KIND_ILLEGAL;
  nt->kind = DEBUG_KIND_ILLEGAL;
 
 
  nt->next = h->types;
  nt->next = h->types;
  h->types = nt;
  h->types = nt;
 
 
  if (found)
  if (found)
    {
    {
      /* This is one of the builtin typedefs, so we don't need to
      /* This is one of the builtin typedefs, so we don't need to
         actually define it.  */
         actually define it.  */
      ieee_pop_unused_type (info);
      ieee_pop_unused_type (info);
      return TRUE;
      return TRUE;
    }
    }
 
 
  indx = ieee_pop_type (info);
  indx = ieee_pop_type (info);
 
 
  if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
  if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
                                type.unsignedp, localp,
                                type.unsignedp, localp,
                                (struct ieee_buflist *) NULL)
                                (struct ieee_buflist *) NULL)
      || ! ieee_write_number (info, 'T')
      || ! ieee_write_number (info, 'T')
      || ! ieee_write_number (info, indx))
      || ! ieee_write_number (info, indx))
    return FALSE;
    return FALSE;
 
 
  /* Remove the type we just added to the type stack.  This should not
  /* Remove the type we just added to the type stack.  This should not
     be ieee_pop_unused_type, since the type is used, we just don't
     be ieee_pop_unused_type, since the type is used, we just don't
     need it now.  */
     need it now.  */
  (void) ieee_pop_type (info);
  (void) ieee_pop_type (info);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a tag for a type.  We don't have to do anything here.  */
/* Output a tag for a type.  We don't have to do anything here.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_tag (void *p, const char *name ATTRIBUTE_UNUSED)
ieee_tag (void *p, const char *name ATTRIBUTE_UNUSED)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  /* This should not be ieee_pop_unused_type, since we want the type
  /* This should not be ieee_pop_unused_type, since we want the type
     to be defined.  */
     to be defined.  */
  (void) ieee_pop_type (info);
  (void) ieee_pop_type (info);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output an integer constant.  */
/* Output an integer constant.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_int_constant (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED,
ieee_int_constant (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED,
                   bfd_vma val ATTRIBUTE_UNUSED)
                   bfd_vma val ATTRIBUTE_UNUSED)
{
{
  /* FIXME.  */
  /* FIXME.  */
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a floating point constant.  */
/* Output a floating point constant.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_float_constant (void *p ATTRIBUTE_UNUSED,
ieee_float_constant (void *p ATTRIBUTE_UNUSED,
                     const char *name ATTRIBUTE_UNUSED,
                     const char *name ATTRIBUTE_UNUSED,
                     double val ATTRIBUTE_UNUSED)
                     double val ATTRIBUTE_UNUSED)
{
{
  /* FIXME.  */
  /* FIXME.  */
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a typed constant.  */
/* Output a typed constant.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_typed_constant (void *p, const char *name ATTRIBUTE_UNUSED,
ieee_typed_constant (void *p, const char *name ATTRIBUTE_UNUSED,
                     bfd_vma val ATTRIBUTE_UNUSED)
                     bfd_vma val ATTRIBUTE_UNUSED)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  /* FIXME.  */
  /* FIXME.  */
  ieee_pop_unused_type (info);
  ieee_pop_unused_type (info);
  return TRUE;
  return TRUE;
}
}
 
 
/* Output a variable.  */
/* Output a variable.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_variable (void *p, const char *name, enum debug_var_kind kind,
ieee_variable (void *p, const char *name, enum debug_var_kind kind,
               bfd_vma val)
               bfd_vma val)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  unsigned int name_indx;
  unsigned int name_indx;
  unsigned int size;
  unsigned int size;
  bfd_boolean referencep;
  bfd_boolean referencep;
  unsigned int type_indx;
  unsigned int type_indx;
  bfd_boolean asn;
  bfd_boolean asn;
  int refflag;
  int refflag;
 
 
  size = info->type_stack->type.size;
  size = info->type_stack->type.size;
  referencep = info->type_stack->type.referencep;
  referencep = info->type_stack->type.referencep;
  type_indx = ieee_pop_type (info);
  type_indx = ieee_pop_type (info);
 
 
  assert (! ieee_buffer_emptyp (&info->vars));
  assert (! ieee_buffer_emptyp (&info->vars));
  if (! ieee_change_buffer (info, &info->vars))
  if (! ieee_change_buffer (info, &info->vars))
    return FALSE;
    return FALSE;
 
 
  name_indx = info->name_indx;
  name_indx = info->name_indx;
  ++info->name_indx;
  ++info->name_indx;
 
 
  /* Write out an NN and an ATN record for this variable.  */
  /* Write out an NN and an ATN record for this variable.  */
  if (! ieee_write_byte (info, (int) ieee_nn_record)
  if (! ieee_write_byte (info, (int) ieee_nn_record)
      || ! ieee_write_number (info, name_indx)
      || ! ieee_write_number (info, name_indx)
      || ! ieee_write_id (info, name)
      || ! ieee_write_id (info, name)
      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
      || ! ieee_write_number (info, name_indx)
      || ! ieee_write_number (info, name_indx)
      || ! ieee_write_number (info, type_indx))
      || ! ieee_write_number (info, type_indx))
    return FALSE;
    return FALSE;
  switch (kind)
  switch (kind)
    {
    {
    default:
    default:
      abort ();
      abort ();
      return FALSE;
      return FALSE;
    case DEBUG_GLOBAL:
    case DEBUG_GLOBAL:
      if (! ieee_write_number (info, 8)
      if (! ieee_write_number (info, 8)
          || ! ieee_add_range (info, FALSE, val, val + size))
          || ! ieee_add_range (info, FALSE, val, val + size))
        return FALSE;
        return FALSE;
      refflag = 0;
      refflag = 0;
      asn = TRUE;
      asn = TRUE;
      break;
      break;
    case DEBUG_STATIC:
    case DEBUG_STATIC:
      if (! ieee_write_number (info, 3)
      if (! ieee_write_number (info, 3)
          || ! ieee_add_range (info, FALSE, val, val + size))
          || ! ieee_add_range (info, FALSE, val, val + size))
        return FALSE;
        return FALSE;
      refflag = 1;
      refflag = 1;
      asn = TRUE;
      asn = TRUE;
      break;
      break;
    case DEBUG_LOCAL_STATIC:
    case DEBUG_LOCAL_STATIC:
      if (! ieee_write_number (info, 3)
      if (! ieee_write_number (info, 3)
          || ! ieee_add_range (info, FALSE, val, val + size))
          || ! ieee_add_range (info, FALSE, val, val + size))
        return FALSE;
        return FALSE;
      refflag = 2;
      refflag = 2;
      asn = TRUE;
      asn = TRUE;
      break;
      break;
    case DEBUG_LOCAL:
    case DEBUG_LOCAL:
      if (! ieee_write_number (info, 1)
      if (! ieee_write_number (info, 1)
          || ! ieee_write_number (info, val))
          || ! ieee_write_number (info, val))
        return FALSE;
        return FALSE;
      refflag = 2;
      refflag = 2;
      asn = FALSE;
      asn = FALSE;
      break;
      break;
    case DEBUG_REGISTER:
    case DEBUG_REGISTER:
      if (! ieee_write_number (info, 2)
      if (! ieee_write_number (info, 2)
          || ! ieee_write_number (info,
          || ! ieee_write_number (info,
                                  ieee_genreg_to_regno (info->abfd, val)))
                                  ieee_genreg_to_regno (info->abfd, val)))
        return FALSE;
        return FALSE;
      refflag = 2;
      refflag = 2;
      asn = FALSE;
      asn = FALSE;
      break;
      break;
    }
    }
 
 
  if (asn)
  if (asn)
    {
    {
      if (! ieee_write_asn (info, name_indx, val))
      if (! ieee_write_asn (info, name_indx, val))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* If this is really a reference type, then we just output it with
  /* If this is really a reference type, then we just output it with
     pointer type, and must now output a C++ record indicating that it
     pointer type, and must now output a C++ record indicating that it
     is really reference type.  */
     is really reference type.  */
  if (referencep)
  if (referencep)
    {
    {
      unsigned int nindx;
      unsigned int nindx;
 
 
      nindx = info->name_indx;
      nindx = info->name_indx;
      ++info->name_indx;
      ++info->name_indx;
 
 
      /* If this is a global variable, we want to output the misc
      /* If this is a global variable, we want to output the misc
         record in the C++ misc record block.  Otherwise, we want to
         record in the C++ misc record block.  Otherwise, we want to
         output it just after the variable definition, which is where
         output it just after the variable definition, which is where
         the current buffer is.  */
         the current buffer is.  */
      if (refflag != 2)
      if (refflag != 2)
        {
        {
          if (! ieee_change_buffer (info, &info->cxx))
          if (! ieee_change_buffer (info, &info->cxx))
            return FALSE;
            return FALSE;
        }
        }
 
 
      if (! ieee_write_byte (info, (int) ieee_nn_record)
      if (! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, 3)
          || ! ieee_write_number (info, 3)
          || ! ieee_write_asn (info, nindx, 'R')
          || ! ieee_write_asn (info, nindx, 'R')
          || ! ieee_write_asn (info, nindx, refflag)
          || ! ieee_write_asn (info, nindx, refflag)
          || ! ieee_write_atn65 (info, nindx, name))
          || ! ieee_write_atn65 (info, nindx, name))
        return FALSE;
        return FALSE;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start outputting information for a function.  */
/* Start outputting information for a function.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_function (void *p, const char *name, bfd_boolean global)
ieee_start_function (void *p, const char *name, bfd_boolean global)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  bfd_boolean referencep;
  bfd_boolean referencep;
  unsigned int retindx, typeindx;
  unsigned int retindx, typeindx;
 
 
  referencep = info->type_stack->type.referencep;
  referencep = info->type_stack->type.referencep;
  retindx = ieee_pop_type (info);
  retindx = ieee_pop_type (info);
 
 
  /* Besides recording a BB4 or BB6 block, we record the type of the
  /* Besides recording a BB4 or BB6 block, we record the type of the
     function in the BB1 typedef block.  We can't write out the full
     function in the BB1 typedef block.  We can't write out the full
     type until we have seen all the parameters, so we accumulate it
     type until we have seen all the parameters, so we accumulate it
     in info->fntype and info->fnargs.  */
     in info->fntype and info->fnargs.  */
  if (! ieee_buffer_emptyp (&info->fntype))
  if (! ieee_buffer_emptyp (&info->fntype))
    {
    {
      /* FIXME: This might happen someday if we support nested
      /* FIXME: This might happen someday if we support nested
         functions.  */
         functions.  */
      abort ();
      abort ();
    }
    }
 
 
  info->fnname = name;
  info->fnname = name;
 
 
  /* An attribute of 0x40 means that the push mask is unknown.  */
  /* An attribute of 0x40 means that the push mask is unknown.  */
  if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, FALSE, TRUE,
  if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, FALSE, TRUE,
                                &info->fntype)
                                &info->fntype)
      || ! ieee_write_number (info, 'x')
      || ! ieee_write_number (info, 'x')
      || ! ieee_write_number (info, 0x40)
      || ! ieee_write_number (info, 0x40)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, 0)
      || ! ieee_write_number (info, retindx))
      || ! ieee_write_number (info, retindx))
    return FALSE;
    return FALSE;
 
 
  typeindx = ieee_pop_type (info);
  typeindx = ieee_pop_type (info);
 
 
  if (! ieee_init_buffer (info, &info->fnargs))
  if (! ieee_init_buffer (info, &info->fnargs))
    return FALSE;
    return FALSE;
  info->fnargcount = 0;
  info->fnargcount = 0;
 
 
  /* If the function return value is actually a reference type, we
  /* If the function return value is actually a reference type, we
     must add a record indicating that.  */
     must add a record indicating that.  */
  if (referencep)
  if (referencep)
    {
    {
      unsigned int nindx;
      unsigned int nindx;
 
 
      nindx = info->name_indx;
      nindx = info->name_indx;
      ++info->name_indx;
      ++info->name_indx;
      if (! ieee_change_buffer (info, &info->cxx)
      if (! ieee_change_buffer (info, &info->cxx)
          || ! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, 3)
          || ! ieee_write_number (info, 3)
          || ! ieee_write_asn (info, nindx, 'R')
          || ! ieee_write_asn (info, nindx, 'R')
          || ! ieee_write_asn (info, nindx, global ? 0 : 1)
          || ! ieee_write_asn (info, nindx, global ? 0 : 1)
          || ! ieee_write_atn65 (info, nindx, name))
          || ! ieee_write_atn65 (info, nindx, name))
        return FALSE;
        return FALSE;
    }
    }
 
 
  assert (! ieee_buffer_emptyp (&info->vars));
  assert (! ieee_buffer_emptyp (&info->vars));
  if (! ieee_change_buffer (info, &info->vars))
  if (! ieee_change_buffer (info, &info->vars))
    return FALSE;
    return FALSE;
 
 
  /* The address is written out as the first block.  */
  /* The address is written out as the first block.  */
 
 
  ++info->block_depth;
  ++info->block_depth;
 
 
  return (ieee_write_byte (info, (int) ieee_bb_record_enum)
  return (ieee_write_byte (info, (int) ieee_bb_record_enum)
          && ieee_write_byte (info, global ? 4 : 6)
          && ieee_write_byte (info, global ? 4 : 6)
          && ieee_write_number (info, 0)
          && ieee_write_number (info, 0)
          && ieee_write_id (info, name)
          && ieee_write_id (info, name)
          && ieee_write_number (info, 0)
          && ieee_write_number (info, 0)
          && ieee_write_number (info, typeindx));
          && ieee_write_number (info, typeindx));
}
}
 
 
/* Add a function parameter.  This will normally be called before the
/* Add a function parameter.  This will normally be called before the
   first block, so we postpone them until we see the block.  */
   first block, so we postpone them until we see the block.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
ieee_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
                         bfd_vma val)
                         bfd_vma val)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_pending_parm *m, **pm;
  struct ieee_pending_parm *m, **pm;
 
 
  assert (info->block_depth == 1);
  assert (info->block_depth == 1);
 
 
  m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
  m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
  memset (m, 0, sizeof *m);
  memset (m, 0, sizeof *m);
 
 
  m->next = NULL;
  m->next = NULL;
  m->name = name;
  m->name = name;
  m->referencep = info->type_stack->type.referencep;
  m->referencep = info->type_stack->type.referencep;
  m->type = ieee_pop_type (info);
  m->type = ieee_pop_type (info);
  m->kind = kind;
  m->kind = kind;
  m->val = val;
  m->val = val;
 
 
  for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
  for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
    ;
    ;
  *pm = m;
  *pm = m;
 
 
  /* Add the type to the fnargs list.  */
  /* Add the type to the fnargs list.  */
  if (! ieee_change_buffer (info, &info->fnargs)
  if (! ieee_change_buffer (info, &info->fnargs)
      || ! ieee_write_number (info, m->type))
      || ! ieee_write_number (info, m->type))
    return FALSE;
    return FALSE;
  ++info->fnargcount;
  ++info->fnargcount;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Output pending function parameters.  */
/* Output pending function parameters.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_output_pending_parms (struct ieee_handle *info)
ieee_output_pending_parms (struct ieee_handle *info)
{
{
  struct ieee_pending_parm *m;
  struct ieee_pending_parm *m;
  unsigned int refcount;
  unsigned int refcount;
 
 
  refcount = 0;
  refcount = 0;
  for (m = info->pending_parms; m != NULL; m = m->next)
  for (m = info->pending_parms; m != NULL; m = m->next)
    {
    {
      enum debug_var_kind vkind;
      enum debug_var_kind vkind;
 
 
      switch (m->kind)
      switch (m->kind)
        {
        {
        default:
        default:
          abort ();
          abort ();
          return FALSE;
          return FALSE;
        case DEBUG_PARM_STACK:
        case DEBUG_PARM_STACK:
        case DEBUG_PARM_REFERENCE:
        case DEBUG_PARM_REFERENCE:
          vkind = DEBUG_LOCAL;
          vkind = DEBUG_LOCAL;
          break;
          break;
        case DEBUG_PARM_REG:
        case DEBUG_PARM_REG:
        case DEBUG_PARM_REF_REG:
        case DEBUG_PARM_REF_REG:
          vkind = DEBUG_REGISTER;
          vkind = DEBUG_REGISTER;
          break;
          break;
        }
        }
 
 
      if (! ieee_push_type (info, m->type, 0, FALSE, FALSE))
      if (! ieee_push_type (info, m->type, 0, FALSE, FALSE))
        return FALSE;
        return FALSE;
      info->type_stack->type.referencep = m->referencep;
      info->type_stack->type.referencep = m->referencep;
      if (m->referencep)
      if (m->referencep)
        ++refcount;
        ++refcount;
      if (! ieee_variable ((void *) info, m->name, vkind, m->val))
      if (! ieee_variable ((void *) info, m->name, vkind, m->val))
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* If there are any reference parameters, we need to output a
  /* If there are any reference parameters, we need to output a
     miscellaneous record indicating them.  */
     miscellaneous record indicating them.  */
  if (refcount > 0)
  if (refcount > 0)
    {
    {
      unsigned int nindx, varindx;
      unsigned int nindx, varindx;
 
 
      /* FIXME: The MRI compiler outputs the demangled function name
      /* FIXME: The MRI compiler outputs the demangled function name
         here, but we are outputting the mangled name.  */
         here, but we are outputting the mangled name.  */
      nindx = info->name_indx;
      nindx = info->name_indx;
      ++info->name_indx;
      ++info->name_indx;
      if (! ieee_change_buffer (info, &info->vars)
      if (! ieee_change_buffer (info, &info->vars)
          || ! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_byte (info, (int) ieee_nn_record)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, nindx)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 62)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, 80)
          || ! ieee_write_number (info, refcount + 3)
          || ! ieee_write_number (info, refcount + 3)
          || ! ieee_write_asn (info, nindx, 'B')
          || ! ieee_write_asn (info, nindx, 'B')
          || ! ieee_write_atn65 (info, nindx, info->fnname)
          || ! ieee_write_atn65 (info, nindx, info->fnname)
          || ! ieee_write_asn (info, nindx, 0))
          || ! ieee_write_asn (info, nindx, 0))
        return FALSE;
        return FALSE;
      for (m = info->pending_parms, varindx = 1;
      for (m = info->pending_parms, varindx = 1;
           m != NULL;
           m != NULL;
           m = m->next, varindx++)
           m = m->next, varindx++)
        {
        {
          if (m->referencep)
          if (m->referencep)
            {
            {
              if (! ieee_write_asn (info, nindx, varindx))
              if (! ieee_write_asn (info, nindx, varindx))
                return FALSE;
                return FALSE;
            }
            }
        }
        }
    }
    }
 
 
  m = info->pending_parms;
  m = info->pending_parms;
  while (m != NULL)
  while (m != NULL)
    {
    {
      struct ieee_pending_parm *next;
      struct ieee_pending_parm *next;
 
 
      next = m->next;
      next = m->next;
      free (m);
      free (m);
      m = next;
      m = next;
    }
    }
 
 
  info->pending_parms = NULL;
  info->pending_parms = NULL;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Start a block.  If this is the first block, we output the address
/* Start a block.  If this is the first block, we output the address
   to finish the BB4 or BB6, and then output the function parameters.  */
   to finish the BB4 or BB6, and then output the function parameters.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_start_block (void *p, bfd_vma addr)
ieee_start_block (void *p, bfd_vma addr)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  if (! ieee_change_buffer (info, &info->vars))
  if (! ieee_change_buffer (info, &info->vars))
    return FALSE;
    return FALSE;
 
 
  if (info->block_depth == 1)
  if (info->block_depth == 1)
    {
    {
      if (! ieee_write_number (info, addr)
      if (! ieee_write_number (info, addr)
          || ! ieee_output_pending_parms (info))
          || ! ieee_output_pending_parms (info))
        return FALSE;
        return FALSE;
    }
    }
  else
  else
    {
    {
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, 6)
          || ! ieee_write_byte (info, 6)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, "")
          || ! ieee_write_id (info, "")
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, addr))
          || ! ieee_write_number (info, addr))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_start_range (info, addr))
  if (! ieee_start_range (info, addr))
    return FALSE;
    return FALSE;
 
 
  ++info->block_depth;
  ++info->block_depth;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* End a block.  */
/* End a block.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_end_block (void *p, bfd_vma addr)
ieee_end_block (void *p, bfd_vma addr)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  /* The address we are given is the end of the block, but IEEE seems
  /* The address we are given is the end of the block, but IEEE seems
     to want to the address of the last byte in the block, so we
     to want to the address of the last byte in the block, so we
     subtract one.  */
     subtract one.  */
  if (! ieee_change_buffer (info, &info->vars)
  if (! ieee_change_buffer (info, &info->vars)
      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
      || ! ieee_write_number (info, addr - 1))
      || ! ieee_write_number (info, addr - 1))
    return FALSE;
    return FALSE;
 
 
  if (! ieee_end_range (info, addr))
  if (! ieee_end_range (info, addr))
    return FALSE;
    return FALSE;
 
 
  --info->block_depth;
  --info->block_depth;
 
 
  if (addr > info->highaddr)
  if (addr > info->highaddr)
    info->highaddr = addr;
    info->highaddr = addr;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* End a function.  */
/* End a function.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_end_function (void *p)
ieee_end_function (void *p)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  assert (info->block_depth == 1);
  assert (info->block_depth == 1);
 
 
  --info->block_depth;
  --info->block_depth;
 
 
  /* Now we can finish up fntype, and add it to the typdef section.
  /* Now we can finish up fntype, and add it to the typdef section.
     At this point, fntype is the 'x' type up to the argument count,
     At this point, fntype is the 'x' type up to the argument count,
     and fnargs is the argument types.  We must add the argument
     and fnargs is the argument types.  We must add the argument
     count, and we must add the level.  FIXME: We don't record varargs
     count, and we must add the level.  FIXME: We don't record varargs
     functions correctly.  In fact, stabs debugging does not give us
     functions correctly.  In fact, stabs debugging does not give us
     enough information to do so.  */
     enough information to do so.  */
  if (! ieee_change_buffer (info, &info->fntype)
  if (! ieee_change_buffer (info, &info->fntype)
      || ! ieee_write_number (info, info->fnargcount)
      || ! ieee_write_number (info, info->fnargcount)
      || ! ieee_change_buffer (info, &info->fnargs)
      || ! ieee_change_buffer (info, &info->fnargs)
      || ! ieee_write_number (info, 0))
      || ! ieee_write_number (info, 0))
    return FALSE;
    return FALSE;
 
 
  /* Make sure the typdef block has been started.  */
  /* Make sure the typdef block has been started.  */
  if (ieee_buffer_emptyp (&info->types))
  if (ieee_buffer_emptyp (&info->types))
    {
    {
      if (! ieee_change_buffer (info, &info->types)
      if (! ieee_change_buffer (info, &info->types)
          || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
          || ! ieee_write_byte (info, 1)
          || ! ieee_write_byte (info, 1)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_id (info, info->modname))
          || ! ieee_write_id (info, info->modname))
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (! ieee_append_buffer (info, &info->types, &info->fntype)
  if (! ieee_append_buffer (info, &info->types, &info->fntype)
      || ! ieee_append_buffer (info, &info->types, &info->fnargs))
      || ! ieee_append_buffer (info, &info->types, &info->fnargs))
    return FALSE;
    return FALSE;
 
 
  info->fnname = NULL;
  info->fnname = NULL;
  if (! ieee_init_buffer (info, &info->fntype)
  if (! ieee_init_buffer (info, &info->fntype)
      || ! ieee_init_buffer (info, &info->fnargs))
      || ! ieee_init_buffer (info, &info->fnargs))
    return FALSE;
    return FALSE;
  info->fnargcount = 0;
  info->fnargcount = 0;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Record line number information.  */
/* Record line number information.  */
 
 
static bfd_boolean
static bfd_boolean
ieee_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
ieee_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
{
{
  struct ieee_handle *info = (struct ieee_handle *) p;
  struct ieee_handle *info = (struct ieee_handle *) p;
 
 
  assert (info->filename != NULL);
  assert (info->filename != NULL);
 
 
  /* The HP simulator seems to get confused when more than one line is
  /* The HP simulator seems to get confused when more than one line is
     listed for the same address, at least if they are in different
     listed for the same address, at least if they are in different
     files.  We handle this by always listing the last line for a
     files.  We handle this by always listing the last line for a
     given address, since that seems to be the one that gdb uses.  */
     given address, since that seems to be the one that gdb uses.  */
  if (info->pending_lineno_filename != NULL
  if (info->pending_lineno_filename != NULL
      && addr != info->pending_lineno_addr)
      && addr != info->pending_lineno_addr)
    {
    {
      /* Make sure we have a line number block.  */
      /* Make sure we have a line number block.  */
      if (! ieee_buffer_emptyp (&info->linenos))
      if (! ieee_buffer_emptyp (&info->linenos))
        {
        {
          if (! ieee_change_buffer (info, &info->linenos))
          if (! ieee_change_buffer (info, &info->linenos))
            return FALSE;
            return FALSE;
        }
        }
      else
      else
        {
        {
          info->lineno_name_indx = info->name_indx;
          info->lineno_name_indx = info->name_indx;
          ++info->name_indx;
          ++info->name_indx;
          if (! ieee_change_buffer (info, &info->linenos)
          if (! ieee_change_buffer (info, &info->linenos)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
              || ! ieee_write_byte (info, 5)
              || ! ieee_write_byte (info, 5)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_number (info, 0)
              || ! ieee_write_id (info, info->filename)
              || ! ieee_write_id (info, info->filename)
              || ! ieee_write_byte (info, (int) ieee_nn_record)
              || ! ieee_write_byte (info, (int) ieee_nn_record)
              || ! ieee_write_number (info, info->lineno_name_indx)
              || ! ieee_write_number (info, info->lineno_name_indx)
              || ! ieee_write_id (info, ""))
              || ! ieee_write_id (info, ""))
            return FALSE;
            return FALSE;
          info->lineno_filename = info->filename;
          info->lineno_filename = info->filename;
        }
        }
 
 
      if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
      if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
        {
        {
          if (strcmp (info->filename, info->lineno_filename) != 0)
          if (strcmp (info->filename, info->lineno_filename) != 0)
            {
            {
              /* We were not in the main file.  Close the block for the
              /* We were not in the main file.  Close the block for the
                 included file.  */
                 included file.  */
              if (! ieee_write_byte (info, (int) ieee_be_record_enum))
              if (! ieee_write_byte (info, (int) ieee_be_record_enum))
                return FALSE;
                return FALSE;
              if (strcmp (info->filename, info->pending_lineno_filename) == 0)
              if (strcmp (info->filename, info->pending_lineno_filename) == 0)
                {
                {
                  /* We need a new NN record, and we aren't about to
                  /* We need a new NN record, and we aren't about to
                     output one.  */
                     output one.  */
                  info->lineno_name_indx = info->name_indx;
                  info->lineno_name_indx = info->name_indx;
                  ++info->name_indx;
                  ++info->name_indx;
                  if (! ieee_write_byte (info, (int) ieee_nn_record)
                  if (! ieee_write_byte (info, (int) ieee_nn_record)
                      || ! ieee_write_number (info, info->lineno_name_indx)
                      || ! ieee_write_number (info, info->lineno_name_indx)
                      || ! ieee_write_id (info, ""))
                      || ! ieee_write_id (info, ""))
                    return FALSE;
                    return FALSE;
                }
                }
            }
            }
          if (strcmp (info->filename, info->pending_lineno_filename) != 0)
          if (strcmp (info->filename, info->pending_lineno_filename) != 0)
            {
            {
              /* We are not changing to the main file.  Open a block for
              /* We are not changing to the main file.  Open a block for
                 the new included file.  */
                 the new included file.  */
              info->lineno_name_indx = info->name_indx;
              info->lineno_name_indx = info->name_indx;
              ++info->name_indx;
              ++info->name_indx;
              if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
              if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
                  || ! ieee_write_byte (info, 5)
                  || ! ieee_write_byte (info, 5)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_number (info, 0)
                  || ! ieee_write_id (info, info->pending_lineno_filename)
                  || ! ieee_write_id (info, info->pending_lineno_filename)
                  || ! ieee_write_byte (info, (int) ieee_nn_record)
                  || ! ieee_write_byte (info, (int) ieee_nn_record)
                  || ! ieee_write_number (info, info->lineno_name_indx)
                  || ! ieee_write_number (info, info->lineno_name_indx)
                  || ! ieee_write_id (info, ""))
                  || ! ieee_write_id (info, ""))
                return FALSE;
                return FALSE;
            }
            }
          info->lineno_filename = info->pending_lineno_filename;
          info->lineno_filename = info->pending_lineno_filename;
        }
        }
 
 
      if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
      if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
          || ! ieee_write_number (info, info->lineno_name_indx)
          || ! ieee_write_number (info, info->lineno_name_indx)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 7)
          || ! ieee_write_number (info, 7)
          || ! ieee_write_number (info, info->pending_lineno)
          || ! ieee_write_number (info, info->pending_lineno)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_number (info, 0)
          || ! ieee_write_asn (info, info->lineno_name_indx,
          || ! ieee_write_asn (info, info->lineno_name_indx,
                               info->pending_lineno_addr))
                               info->pending_lineno_addr))
        return FALSE;
        return FALSE;
    }
    }
 
 
  info->pending_lineno_filename = filename;
  info->pending_lineno_filename = filename;
  info->pending_lineno = lineno;
  info->pending_lineno = lineno;
  info->pending_lineno_addr = addr;
  info->pending_lineno_addr = addr;
 
 
  return TRUE;
  return TRUE;
}
}
 
 

powered by: WebSVN 2.1.0

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