#include "defs.h"
#include "gdb_string.h"
#include "bfd.h"
#include "gdb_obstack.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "symfile.h"
#include "objfiles.h"
#include "aout/stab_gnu.h"
#include "libaout.h"
#include "aout/aout64.h"
#include "gdb-stabs.h"
#include "buildsym.h"
#include "complaints.h"
#include "demangle.h"
#include "language.h"
#include "doublest.h"
#include "cp-abi.h"
#include "cp-support.h"
#include "gdb_assert.h"
#include <ctype.h>
#define EXTERN
#include "stabsread.h"
#undef EXTERN
extern void _initialize_stabsread (void);
struct field_info
{
struct nextfield
{
struct nextfield *next;
int visibility;
struct field field;
}
*list;
struct next_fnfieldlist
{
struct next_fnfieldlist *next;
struct fn_fieldlist fn_fieldlist;
}
*fnlist;
};
static void
read_one_struct_field (struct field_info *, char **, char *,
struct type *, struct objfile *);
static struct type *dbx_alloc_type (int[2], struct objfile *);
static long read_huge_number (char **, int, int *, int);
static struct type *error_type (char **, struct objfile *);
static void
patch_block_stabs (struct pending *, struct pending_stabs *,
struct objfile *);
static void fix_common_block (struct symbol *, int);
static int read_type_number (char **, int *);
static struct type *read_type (char **, struct objfile *);
static struct type *read_range_type (char **, int[2], int, struct objfile *);
static struct type *read_sun_builtin_type (char **, int[2], struct objfile *);
static struct type *read_sun_floating_type (char **, int[2],
struct objfile *);
static struct type *read_enum_type (char **, struct type *, struct objfile *);
static struct type *rs6000_builtin_type (int, struct objfile *);
static int
read_member_functions (struct field_info *, char **, struct type *,
struct objfile *);
static int
read_struct_fields (struct field_info *, char **, struct type *,
struct objfile *);
static int
read_baseclasses (struct field_info *, char **, struct type *,
struct objfile *);
static int
read_tilde_fields (struct field_info *, char **, struct type *,
struct objfile *);
static int attach_fn_fields_to_type (struct field_info *, struct type *);
static int attach_fields_to_type (struct field_info *, struct type *,
struct objfile *);
static struct type *read_struct_type (char **, struct type *,
enum type_code,
struct objfile *);
static struct type *read_array_type (char **, struct type *,
struct objfile *);
static struct field *read_args (char **, int, struct objfile *, int *, int *);
static void add_undefined_type (struct type *);
static void add_undefined_field (struct field *field);
static int
read_cpp_abbrev (struct field_info *, char **, struct type *,
struct objfile *);
char *find_name_end (char *name);
static int process_reference (char **string);
void stabsread_clear_cache (void);
static void adjust_field_bitsize (struct field *field);
static const char vptr_name[] = "_vptr$";
static const char vb_name[] = "_vb$";
#if !defined (BELIEVE_PCC_PROMOTION)
#define BELIEVE_PCC_PROMOTION 0
#endif
static void
invalid_cpp_abbrev_complaint (const char *arg1)
{
complaint (&symfile_complaints, _("invalid C++ abbreviation `%s'"), arg1);
}
static void
reg_value_complaint (int regnum, int num_regs, const char *sym)
{
complaint (&symfile_complaints,
_("register number %d too large (max %d) in symbol %s"),
regnum, num_regs - 1, sym);
}
static void
stabs_general_complaint (const char *arg1)
{
complaint (&symfile_complaints, "%s", arg1);
}
static struct type **undef_types;
static int undef_types_allocated;
static int undef_types_length;
static struct field **undef_fields;
static int undef_fields_allocated;
static int undef_fields_length;
static struct symbol *current_symbol = NULL;
#define STABS_CONTINUE(pp,objfile) \
do { \
if (**(pp) == '\\' || (**(pp) == '?' && (*(pp))[1] == '\0')) \
*(pp) = next_symbol_text (objfile); \
} while (0)
struct type **
dbx_lookup_type (int typenums[2], struct objfile *objfile)
{
int filenum = typenums[0];
int index = typenums[1];
unsigned old_len;
int real_filenum;
struct header_file *f;
int f_orig_length;
if (filenum == -1)
return 0;
if (filenum < 0 || filenum >= n_this_object_header_files)
{
complaint (&symfile_complaints,
_("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d."),
filenum, index, symnum);
goto error_return;
}
if (filenum == 0)
{
if (index < 0)
{
static struct type *temp_type;
temp_type = rs6000_builtin_type (index, objfile);
return &temp_type;
}
if (index >= type_vector_length)
{
old_len = type_vector_length;
if (old_len == 0)
{
type_vector_length = INITIAL_TYPE_VECTOR_LENGTH;
type_vector = (struct type **)
xmalloc (type_vector_length * sizeof (struct type *));
}
while (index >= type_vector_length)
{
type_vector_length *= 2;
}
type_vector = (struct type **)
xrealloc ((char *) type_vector,
(type_vector_length * sizeof (struct type *)));
memset (&type_vector[old_len], 0,
(type_vector_length - old_len) * sizeof (struct type *));
}
return (&type_vector[index]);
}
else
{
real_filenum = this_object_header_files[filenum];
if (real_filenum >= N_HEADER_FILES (current_objfile))
{
struct type *temp_type;
struct type **temp_type_p;
warning (_("GDB internal error: bad real_filenum"));
error_return:
temp_type = init_type (TYPE_CODE_ERROR, 0, 0, NULL, NULL);
temp_type_p = (struct type **) xmalloc (sizeof (struct type *));
*temp_type_p = temp_type;
return temp_type_p;
}
f = HEADER_FILES (current_objfile) + real_filenum;
f_orig_length = f->length;
if (index >= f_orig_length)
{
while (index >= f->length)
{
f->length *= 2;
}
f->vector = (struct type **)
xrealloc ((char *) f->vector, f->length * sizeof (struct type *));
memset (&f->vector[f_orig_length], 0,
(f->length - f_orig_length) * sizeof (struct type *));
}
return (&f->vector[index]);
}
}
static void
dbx_fixup_variants (struct type *real_type)
{
unsigned len = real_type->length;
struct type *variant;
variant = real_type->chain;
while (variant != real_type)
{
if (!TYPE_ADDRESS_CLASS_ALL(variant)
&& TYPE_LENGTH (variant) == 0)
TYPE_LENGTH(variant) = len;
variant = variant->chain;
}
}
static struct type *
dbx_fixup_type (int typenums[2], struct type *new_type, struct objfile *objfile)
{
struct type **type_slot;
type_slot = dbx_lookup_type (typenums, objfile);
if (*type_slot)
{
replace_type (*type_slot, new_type);
return *type_slot;
}
else
{
*type_slot = new_type;
return new_type;
}
}
static struct type *
dbx_alloc_type (int typenums[2], struct objfile *objfile)
{
struct type **type_addr;
if (typenums[0] == -1)
{
return (alloc_type (objfile));
}
type_addr = dbx_lookup_type (typenums, objfile);
if (*type_addr == 0)
{
*type_addr = alloc_type (objfile);
}
return (*type_addr);
}
static void
patch_block_stabs (struct pending *symbols, struct pending_stabs *stabs,
struct objfile *objfile)
{
int ii;
char *name;
char *pp;
struct symbol *sym;
if (stabs)
{
for (ii = 0; ii < stabs->count; ++ii)
{
name = stabs->stab[ii];
pp = (char *) strchr (name, ':');
while (pp[1] == ':')
{
pp += 2;
pp = (char *) strchr (pp, ':');
}
sym = find_symbol_in_list (symbols, name, pp - name);
if (!sym)
{
sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
DEPRECATED_SYMBOL_NAME (sym) =
obsavestring (name, pp - name, &objfile->objfile_obstack);
pp += 2;
if (*(pp - 1) == 'F' || *(pp - 1) == 'f')
{
SYMBOL_TYPE (sym) =
lookup_function_type (read_type (&pp, objfile));
}
else
{
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
}
add_symbol_to_list (sym, &global_symbols);
}
else
{
pp += 2;
if (*(pp - 1) == 'F' || *(pp - 1) == 'f')
{
SYMBOL_TYPE (sym) =
lookup_function_type (read_type (&pp, objfile));
}
else
{
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
}
}
}
}
}
static int
read_type_number (char **pp, int *typenums)
{
int nbits;
if (**pp == '(')
{
(*pp)++;
typenums[0] = read_huge_number (pp, ',', &nbits, 0);
if (nbits != 0)
return -1;
typenums[1] = read_huge_number (pp, ')', &nbits, 0);
if (nbits != 0)
return -1;
}
else
{
typenums[0] = 0;
typenums[1] = read_huge_number (pp, 0, &nbits, 0);
if (nbits != 0)
return -1;
}
return 0;
}
#define VISIBILITY_PRIVATE '0'
#define VISIBILITY_PROTECTED '1'
#define VISIBILITY_PUBLIC '2'
#define VISIBILITY_IGNORE '9'
struct ref_map
{
char *stabs;
CORE_ADDR value;
struct symbol *sym;
};
#define MAX_CHUNK_REFS 100
#define REF_CHUNK_SIZE (MAX_CHUNK_REFS * sizeof (struct ref_map))
#define REF_MAP_SIZE(ref_chunk) ((ref_chunk) * REF_CHUNK_SIZE)
static struct ref_map *ref_map;
static int ref_count = 0;
static int ref_chunk = 0;
void
stabsread_clear_cache (void)
{
ref_count = 0;
ref_chunk = 0;
}
void
ref_add (int refnum, struct symbol *sym, char *stabs, CORE_ADDR value)
{
if (ref_count == 0)
ref_chunk = 0;
if (refnum >= ref_count)
ref_count = refnum + 1;
if (ref_count > ref_chunk * MAX_CHUNK_REFS)
{
int new_slots = ref_count - ref_chunk * MAX_CHUNK_REFS;
int new_chunks = new_slots / MAX_CHUNK_REFS + 1;
ref_map = (struct ref_map *)
xrealloc (ref_map, REF_MAP_SIZE (ref_chunk + new_chunks));
memset (ref_map + ref_chunk * MAX_CHUNK_REFS, 0, new_chunks * REF_CHUNK_SIZE);
ref_chunk += new_chunks;
}
ref_map[refnum].stabs = stabs;
ref_map[refnum].sym = sym;
ref_map[refnum].value = value;
}
struct symbol *
ref_search (int refnum)
{
if (refnum < 0 || refnum > ref_count)
return 0;
return ref_map[refnum].sym;
}
static int
process_reference (char **string)
{
char *p;
int refnum = 0;
if (**string != '#')
return 0;
p = *string + 1;
while (*p && isdigit (*p))
{
refnum = refnum * 10 + *p - '0';
p++;
}
*string = p;
return refnum;
}
int
symbol_reference_defined (char **string)
{
char *p = *string;
int refnum = 0;
refnum = process_reference (&p);
if (*p == '=')
{
*string = p + 1;
return refnum;
}
else
{
*string = p;
return -1;
}
}
void
process_symbol_types_only (char *string, const char *prefix,
int desc, int type, struct objfile *objfile)
{
char *p = (char *) find_name_end (string);
int deftype;
if (prefix == NULL)
{
prefix = "";
}
if (string[0] == 0)
return;
if (p == 0)
return;
while (p[1] == ':')
{
p += 2;
p = strchr (p, ':');
if (p == NULL) {
STABS_CONTINUE (&p, objfile);
p = strchr (p, ':');
}
}
p++;
if (isdigit (*p) || *p == '(' || *p == '-')
deftype = 'l';
else
deftype = *p++;
switch (deftype)
{
case 'c':
if (*(p++) == 'e')
{
read_type (&p, objfile);
if (*p != ',')
complaint (&symfile_complaints, "Bad enum type");
}
break;
case 'C':
case 'f':
case 'F':
case 'G':
case 's':
case 'l':
case 'p':
case 'R':
case 'r':
case 'S':
case 'V':
case 'v':
case 'a':
read_type (&p, objfile);
break;
case 't':
case 'T':
define_symbol (0, string, prefix, desc, type, objfile);
break;
default:
break;
}
}
struct symbol *
define_symbol (CORE_ADDR valu, char *string, const char *prefix,
int desc, int type, struct objfile *objfile)
{
struct symbol *sym;
char *p = (char *) find_name_end (string);
int deftype;
int synonym = 0;
int i;
int nameless;
if (prefix == NULL)
prefix = "";
if (string[0] == 0)
return 0;
if (p == 0)
return 0;
while (p[1] == ':')
{
p += 2;
p = strchr (p, ':');
if (p == NULL) {
STABS_CONTINUE (&p, objfile);
p = strchr (p, ':');
}
}
nameless = (p == string || ((string[0] == ' ') && (string[1] == ':')));
current_symbol = sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
switch (type & N_TYPE)
{
case N_TEXT:
SYMBOL_SECTION (sym) = SECT_OFF_TEXT (objfile);
break;
case N_DATA:
SYMBOL_SECTION (sym) = SECT_OFF_DATA (objfile);
break;
case N_BSS:
SYMBOL_SECTION (sym) = SECT_OFF_BSS (objfile);
break;
}
if (processing_gcc_compilation)
{
SYMBOL_LINE (sym) = desc;
}
else
{
SYMBOL_LINE (sym) = 0;
}
if (is_cplus_marker (string[0]))
{
switch (string[1])
{
case 't':
DEPRECATED_SYMBOL_NAME (sym) = obsavestring ("this", strlen ("this"),
&objfile->objfile_obstack);
break;
case 'v':
goto normal;
case 'e':
DEPRECATED_SYMBOL_NAME (sym) = obsavestring ("eh_throw", strlen ("eh_throw"),
&objfile->objfile_obstack);
break;
case '_':
goto normal;
#ifdef STATIC_TRANSFORM_NAME
case 'X':
goto normal;
#endif
default:
complaint (&symfile_complaints, _("Unknown C++ symbol name `%s'"),
string);
goto normal;
}
}
else
{
unsigned int prefixlen, nlen;
normal:
prefixlen = strlen (prefix);
nlen = p - string;
SYMBOL_LANGUAGE (sym) = current_subfile->language;
SYMBOL_SET_NAMES (sym, string, p - string, objfile);
}
p++;
#if 0
if (!strchr ("cfFGpPrStTvVXCR", *p))
#else
if (isdigit (*p) || *p == '(' || *p == '-')
#endif
deftype = 'l';
else
deftype = *p++;
switch (deftype)
{
case 'c':
if (*p != '=')
{
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = error_type (&p, objfile);
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &file_symbols);
return sym;
}
++p;
switch (*p++)
{
case 'r':
{
double d = atof (p);
char *dbl_valu;
SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile,
FT_DBL_PREC_FLOAT);
dbl_valu = (char *)
obstack_alloc (&objfile->objfile_obstack,
TYPE_LENGTH (SYMBOL_TYPE (sym)));
store_typed_floating (dbl_valu, SYMBOL_TYPE (sym), d);
SYMBOL_VALUE_BYTES (sym) = dbl_valu;
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
}
break;
case 'i':
{
static struct type *int_const_type;
if (int_const_type == NULL)
int_const_type =
init_type (TYPE_CODE_INT,
sizeof (int) * HOST_CHAR_BIT / TARGET_CHAR_BIT, 0,
"integer constant",
(struct objfile *) NULL);
SYMBOL_TYPE (sym) = int_const_type;
SYMBOL_VALUE (sym) = atoi (p);
SYMBOL_CLASS (sym) = LOC_CONST;
}
break;
case 'b':
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "bool", objfile);
if (*p == '0')
SYMBOL_VALUE (sym) = 0;
else if (*p == '1')
SYMBOL_VALUE (sym) = 1;
else
{
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = error_type (&p, objfile);
}
break;
case 'e':
{
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = read_type (&p, objfile);
if (*p != ',')
{
SYMBOL_TYPE (sym) = error_type (&p, objfile);
break;
}
++p;
SYMBOL_VALUE (sym) = atoi (p);
}
break;
default:
{
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = error_type (&p, objfile);
}
}
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &file_symbols);
return sym;
case 'C':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_LABEL;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_VALUE_ADDRESS (sym) = valu;
add_symbol_to_list (sym, &local_symbols);
break;
case 'f':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_BLOCK;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &file_symbols);
process_function_types:
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_FUNC)
SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
process_prototype_types:
if (*p == ';')
{
struct type *ftype = SYMBOL_TYPE (sym);
int nsemi = 0;
int nparams = 0;
char *p1 = p;
while (*p1)
{
if (*p1++ == ';')
nsemi++;
}
TYPE_FIELDS (ftype) = (struct field *)
TYPE_ALLOC (ftype, nsemi * sizeof (struct field));
while (*p++ == ';')
{
struct type *ptype;
if (p[0] == '0' && p[1] == '\0')
break;
ptype = read_type (&p, objfile);
if (TYPE_CODE (ptype) == TYPE_CODE_VOID)
ptype = builtin_type_int;
TYPE_FIELD_TYPE (ftype, nparams) = ptype;
TYPE_FIELD_ARTIFICIAL (ftype, nparams++) = 0;
}
TYPE_NFIELDS (ftype) = nparams;
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
}
break;
case 'F':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_BLOCK;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &global_symbols);
goto process_function_types;
case 'G':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
if (DEPRECATED_SYMBOL_NAME (sym) && DEPRECATED_SYMBOL_NAME (sym)[0] != '#')
{
i = hashname (DEPRECATED_SYMBOL_NAME (sym));
SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
global_sym_chain[i] = sym;
}
add_symbol_to_list (sym, &global_symbols);
break;
case 's':
case 'l':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_LOCAL;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
case 'p':
if (*p == 'F')
{
p++;
SYMBOL_TYPE (sym)
= lookup_pointer_type
(lookup_function_type (read_type (&p, objfile)));
}
else
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_ARG;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG)
{
break;
}
if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
break;
if (!BELIEVE_PCC_PROMOTION)
{
static struct type *pcc_promotion_type;
static struct type *pcc_unsigned_promotion_type;
if (pcc_promotion_type == NULL)
pcc_promotion_type =
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
0, "int", NULL);
if (pcc_unsigned_promotion_type == NULL)
pcc_unsigned_promotion_type =
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned int", NULL);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
&& TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT)
{
SYMBOL_TYPE (sym) =
TYPE_UNSIGNED (SYMBOL_TYPE (sym))
? pcc_unsigned_promotion_type
: pcc_promotion_type;
}
break;
}
case 'P':
if (type == N_FUN)
{
SYMBOL_TYPE (sym) = read_type (&p, objfile);
goto process_prototype_types;
}
case 'R':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_REGPARM;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
if (SYMBOL_VALUE (sym) >= NUM_REGS + NUM_PSEUDO_REGS)
{
reg_value_complaint (SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_PRINT_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
case 'r':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_REGISTER;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
if (SYMBOL_VALUE (sym) >= NUM_REGS + NUM_PSEUDO_REGS)
{
reg_value_complaint (SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_PRINT_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
if (within_function)
{
if (local_symbols
&& local_symbols->nsyms > 0
&& gdbarch_stabs_argument_has_addr (current_gdbarch,
SYMBOL_TYPE (sym)))
{
struct symbol *prev_sym;
prev_sym = local_symbols->symbol[local_symbols->nsyms - 1];
if ((SYMBOL_CLASS (prev_sym) == LOC_REF_ARG
|| SYMBOL_CLASS (prev_sym) == LOC_ARG)
&& strcmp (DEPRECATED_SYMBOL_NAME (prev_sym),
DEPRECATED_SYMBOL_NAME (sym)) == 0)
{
SYMBOL_CLASS (prev_sym) = LOC_REGPARM;
SYMBOL_TYPE (prev_sym) = SYMBOL_TYPE (sym);
SYMBOL_VALUE (prev_sym) = SYMBOL_VALUE (sym);
sym = prev_sym;
break;
}
}
add_symbol_to_list (sym, &local_symbols);
}
else
add_symbol_to_list (sym, &file_symbols);
break;
case 'S':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_VALUE_ADDRESS (sym) = valu;
#ifdef STATIC_TRANSFORM_NAME
if (IS_STATIC_TRANSFORM_NAME (DEPRECATED_SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (sym), NULL, objfile);
if (msym != NULL)
{
DEPRECATED_SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (DEPRECATED_SYMBOL_NAME (sym));
SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
}
}
#endif
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &file_symbols);
break;
case 't':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
if (nameless)
return NULL;
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
if (TYPE_NAME (SYMBOL_TYPE (sym)) != NULL)
if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
&& TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
{
int j;
for (j = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)) - 1; j >= 0; j--)
if (TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) == 0)
TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) =
type_name_no_tag (TYPE_BASECLASS (SYMBOL_TYPE (sym), j));
}
if (TYPE_NAME (SYMBOL_TYPE (sym)) == NULL)
{
extern const char vtbl_ptr_name[];
if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR
&& strcmp (DEPRECATED_SYMBOL_NAME (sym), vtbl_ptr_name))
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC)
{
if (current_subfile->language == language_pascal)
{
TYPE_NAME (SYMBOL_TYPE (sym)) = DEPRECATED_SYMBOL_NAME (sym);
}
}
else
{
struct type *symtype = SYMBOL_TYPE (sym);
TYPE_NAME (SYMBOL_TYPE (sym)) = DEPRECATED_SYMBOL_NAME (sym);
if (TYPE_CODE (symtype) == TYPE_CODE_FLT
&& TYPE_NAME (symtype) != NULL
&& strcmp (TYPE_NAME (symtype), "long double") == 0
&& TYPE_LENGTH (symtype) * TARGET_CHAR_BIT != TARGET_LONG_DOUBLE_BIT)
TYPE_FLOATFORMAT (symtype) = gdbarch_long_double_format (current_gdbarch);
}
}
add_symbol_to_list (sym, &file_symbols);
break;
case 'T':
synonym = *p == 't';
if (synonym)
p++;
SYMBOL_TYPE (sym) = read_type (&p, objfile);
if (nameless)
return NULL;
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_TAG_NAME (SYMBOL_TYPE (sym))
= obconcat (&objfile->objfile_obstack, "", "", DEPRECATED_SYMBOL_NAME (sym));
add_symbol_to_list (sym, &file_symbols);
if (synonym)
{
struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
*typedef_sym = *sym;
SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
SYMBOL_VALUE (typedef_sym) = valu;
SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_NAME (SYMBOL_TYPE (sym))
= obconcat (&objfile->objfile_obstack, "", "", DEPRECATED_SYMBOL_NAME (sym));
add_symbol_to_list (typedef_sym, &file_symbols);
}
break;
case 'V':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_VALUE_ADDRESS (sym) = valu;
#ifdef STATIC_TRANSFORM_NAME
if (IS_STATIC_TRANSFORM_NAME (DEPRECATED_SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (sym), NULL, objfile);
if (msym != NULL)
{
DEPRECATED_SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (DEPRECATED_SYMBOL_NAME (sym));
SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
}
}
#endif
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
case 'v':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_REF_ARG;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
case 'a':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
if (SYMBOL_VALUE (sym) >= NUM_REGS + NUM_PSEUDO_REGS)
{
reg_value_complaint (SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_PRINT_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
case 'X':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_LOCAL;
SYMBOL_VALUE (sym) = valu;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &local_symbols);
break;
default:
SYMBOL_TYPE (sym) = error_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_VALUE (sym) = 0;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, &file_symbols);
break;
}
if (gdbarch_stabs_argument_has_addr (current_gdbarch, SYMBOL_TYPE (sym))
&& (SYMBOL_CLASS (sym) == LOC_REGPARM || SYMBOL_CLASS (sym) == LOC_ARG))
{
if (SYMBOL_CLASS (sym) == LOC_REGPARM)
SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
else if (SYMBOL_CLASS (sym) == LOC_ARG)
SYMBOL_CLASS (sym) = LOC_REF_ARG;
}
return sym;
}
static struct type *
error_type (char **pp, struct objfile *objfile)
{
complaint (&symfile_complaints, _("couldn't parse type; debugger out of date?"));
while (1)
{
while (**pp != '\0')
{
(*pp)++;
}
if ((*pp)[-1] == '\\' || (*pp)[-1] == '?')
{
*pp = next_symbol_text (objfile);
}
else
{
break;
}
}
return (builtin_type_error);
}
static struct type *
read_type (char **pp, struct objfile *objfile)
{
struct type *type = 0;
struct type *type1;
int typenums[2];
char type_descriptor;
int type_size = -1;
int is_string = 0;
int is_vector = 0;
int is_stride = 0;
int stride = 0;
if ((**pp >= '0' && **pp <= '9')
|| **pp == '('
|| **pp == '-')
{
if (read_type_number (pp, typenums) != 0)
return error_type (pp, objfile);
if (**pp != '=')
{
if (typenums[0] == 0 && typenums[1] < 0)
{
if (**pp == ';')
(*pp)++;
}
type = dbx_alloc_type (typenums, objfile);
if (TYPE_CODE (type) == TYPE_CODE_UNDEF)
add_undefined_type (type);
return type;
}
(*pp) += 2;
}
else
{
typenums[0] = typenums[1] = -1;
(*pp)++;
}
again:
type_descriptor = (*pp)[-1];
switch (type_descriptor)
{
case 'x':
{
enum type_code code;
struct pending *ppt;
int i;
char *type_name;
{
char *from, *to, *p, *q1, *q2;
switch ((*pp)[0])
{
case 's':
code = TYPE_CODE_STRUCT;
break;
case 'u':
code = TYPE_CODE_UNION;
break;
case 'e':
code = TYPE_CODE_ENUM;
break;
default:
{
complaint (&symfile_complaints,
_("Unrecognized cross-reference type `%c'"), (*pp)[0]);
code = TYPE_CODE_STRUCT;
break;
}
}
q1 = strchr (*pp, '<');
p = strchr (*pp, ':');
if (p == NULL)
return error_type (pp, objfile);
if (q1 && p > q1 && p[1] == ':')
{
int nesting_level = 0;
for (q2 = q1; *q2; q2++)
{
if (*q2 == '<')
nesting_level++;
else if (*q2 == '>')
nesting_level--;
else if (*q2 == ':' && nesting_level == 0)
break;
}
p = q2;
if (*p != ':')
return error_type (pp, objfile);
}
to = type_name =
(char *) obstack_alloc (&objfile->objfile_obstack, p - *pp + 1);
from = *pp + 1;
while (from < p)
*to++ = *from++;
*to = '\0';
*pp = from + 1;
}
{
struct type **slot_addr = dbx_lookup_type (typenums, objfile);
struct type *this_slot_type = slot_addr ? *slot_addr : NULL;
if (this_slot_type != NULL
&& TYPE_CODE (this_slot_type) != TYPE_CODE_UNDEF)
return this_slot_type;
for (ppt = file_symbols; ppt; ppt = ppt->next)
for (i = 0; i < ppt->nsyms; i++)
{
struct symbol *sym = ppt->symbol[i];
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
&& SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& SYMBOL_TYPE (sym) == this_slot_type
&& (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
&& strcmp (DEPRECATED_SYMBOL_NAME (sym), type_name) == 0)
{
obstack_free (&objfile->objfile_obstack, type_name);
type = SYMBOL_TYPE (sym);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
return type;
}
}
}
type = dbx_alloc_type (typenums, objfile);
TYPE_CODE (type) = code;
TYPE_TAG_NAME (type) = type_name;
INIT_CPLUS_SPECIFIC (type);
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
add_undefined_type (type);
return type;
}
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '(':
(*pp)--;
type = dbx_alloc_type (typenums, objfile);
TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
{
struct type *xtype = read_type (pp, objfile);
if (type == xtype)
{
TYPE_CODE (type) = TYPE_CODE_VOID;
TYPE_LENGTH (type) = 1;
}
else if (type_size >= 0 || is_string)
{
replace_type (type, xtype);
TYPE_NAME (type) = NULL;
TYPE_TAG_NAME (type) = NULL;
}
else
{
TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
TYPE_TARGET_TYPE (type) = xtype;
}
}
break;
case '*':
type1 = read_type (pp, objfile);
type = make_pointer_type (type1, dbx_lookup_type (typenums, objfile));
break;
case '&':
type1 = read_type (pp, objfile);
type = make_reference_type (type1, dbx_lookup_type (typenums, objfile));
break;
case 'f':
type1 = read_type (pp, objfile);
type = make_function_type (type1, dbx_lookup_type (typenums, objfile));
break;
case 'g':
{
const char *type_start = (*pp) - 1;
struct type *return_type = read_type (pp, objfile);
struct type *func_type
= make_function_type (return_type, dbx_lookup_type (typenums, objfile));
struct type_list {
struct type *type;
struct type_list *next;
} *arg_types = 0;
int num_args = 0;
while (**pp && **pp != '#')
{
struct type *arg_type = read_type (pp, objfile);
struct type_list *new = alloca (sizeof (*new));
new->type = arg_type;
new->next = arg_types;
arg_types = new;
num_args++;
}
if (**pp == '#')
++*pp;
else
{
complaint (&symfile_complaints,
_("Prototyped function type didn't end arguments with `#':\n%s"),
type_start);
}
if (arg_types
&& ! arg_types->next
&& TYPE_CODE (arg_types->type) == TYPE_CODE_VOID)
num_args = 0;
TYPE_FIELDS (func_type)
= (struct field *) TYPE_ALLOC (func_type,
num_args * sizeof (struct field));
memset (TYPE_FIELDS (func_type), 0, num_args * sizeof (struct field));
{
int i;
struct type_list *t;
for (t = arg_types, i = num_args - 1; t; t = t->next, i--)
TYPE_FIELD_TYPE (func_type, i) = t->type;
}
TYPE_NFIELDS (func_type) = num_args;
TYPE_FLAGS (func_type) |= TYPE_FLAG_PROTOTYPED;
type = func_type;
break;
}
case 'k':
type = read_type (pp, objfile);
type = make_cv_type (1, TYPE_VOLATILE (type), type,
dbx_lookup_type (typenums, objfile));
break;
case 'B':
type = read_type (pp, objfile);
type = make_cv_type (TYPE_CONST (type), 1, type,
dbx_lookup_type (typenums, objfile));
break;
case '@':
if (isdigit (**pp) || **pp == '(' || **pp == '-')
{
struct type *domain = read_type (pp, objfile);
struct type *memtype;
if (**pp != ',')
return error_type (pp, objfile);
++*pp;
memtype = read_type (pp, objfile);
type = dbx_alloc_type (typenums, objfile);
smash_to_member_type (type, domain, memtype);
}
else
{
char *attr = *pp;
while (**pp != ';' && **pp != '\0')
++(*pp);
if (**pp == '\0')
return error_type (pp, objfile);
else
++ * pp;
switch (*attr)
{
case 's':
type_size = atoi (attr + 1);
if (type_size <= 0)
type_size = -1;
break;
case 'T':
is_stride = 1;
stride = atoi (attr + 2);
break;
case 'S':
is_string = 1;
break;
case 'V':
is_vector = 1;
break;
default:
break;
}
++*pp;
goto again;
}
break;
case '#':
if ((*pp)[0] == '#')
{
struct type *return_type;
(*pp)++;
return_type = read_type (pp, objfile);
if (*(*pp)++ != ';')
complaint (&symfile_complaints,
_("invalid (minimal) member type data format at symtab pos %d."),
symnum);
type = allocate_stub_method (return_type);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
}
else
{
struct type *domain = read_type (pp, objfile);
struct type *return_type;
struct field *args;
int nargs, varargs;
if (**pp != ',')
return error_type (pp, objfile);
else
++(*pp);
return_type = read_type (pp, objfile);
if ((*pp)[0] == ';' && (*pp)[1] == ',')
{
++(*pp);
}
args = read_args (pp, ';', objfile, &nargs, &varargs);
type = dbx_alloc_type (typenums, objfile);
smash_to_method_type (type, domain, return_type, args,
nargs, varargs);
}
break;
case 'r':
type = read_range_type (pp, typenums, type_size, objfile);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
break;
case 'b':
{
type = read_sun_builtin_type (pp, typenums, objfile);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
}
break;
case 'R':
type = read_sun_floating_type (pp, typenums, objfile);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
break;
case 'e':
type = dbx_alloc_type (typenums, objfile);
type = read_enum_type (pp, type, objfile);
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
break;
case 's':
case 'u':
{
enum type_code type_code = TYPE_CODE_UNDEF;
type = dbx_alloc_type (typenums, objfile);
switch (type_descriptor)
{
case 's':
type_code = TYPE_CODE_STRUCT;
break;
case 'u':
type_code = TYPE_CODE_UNION;
break;
}
type = read_struct_type (pp, type, type_code, objfile);
break;
}
case 'a':
if (**pp != 'r')
return error_type (pp, objfile);
++*pp;
type = dbx_alloc_type (typenums, objfile);
type = read_array_type (pp, type, objfile);
if (is_string)
TYPE_CODE (type) = TYPE_CODE_STRING;
if (is_vector)
TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
if (TYPE_CODE (type) == TYPE_CODE_ERROR)
return error_type (pp, objfile);
if (is_stride)
{
if ((stride != 1) && (stride != -1))
complaint (&symfile_complaints,
"invalid stride: unsupported value %d at symtab pos %d.",
stride, symnum);
TYPE_STRIDE (TYPE_INDEX_TYPE (type)) = stride;
}
else
if (TYPE_VECTOR (type)
&& TYPE_OBJFILE (type)
&& TYPE_OBJFILE (type)->obfd
&& (bfd_get_arch (TYPE_OBJFILE (type)->obfd) == bfd_arch_i386))
TYPE_STRIDE (TYPE_INDEX_TYPE (type)) = -1;
else
TYPE_STRIDE (TYPE_INDEX_TYPE (type)) = 1;
break;
case 'S':
type1 = read_type (pp, objfile);
type = create_set_type ((struct type *) NULL, type1);
if (is_string)
TYPE_CODE (type) = TYPE_CODE_BITSTRING;
if (typenums[0] != -1)
type = dbx_fixup_type (typenums, type, objfile);
break;
default:
--*pp;
return error_type (pp, objfile);
}
if (type == 0)
{
warning (_("GDB internal error, type is NULL in stabsread.c."));
return error_type (pp, objfile);
}
if (type_size != -1)
TYPE_LENGTH (type) = (type_size + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
dbx_fixup_variants (type);
return type;
}
static struct type *
rs6000_builtin_type (int typenum, struct objfile *objfile)
{
#define NUMBER_RECOGNIZED 34
static struct type *negative_types[NUMBER_RECOGNIZED + 1];
struct type *rettype = NULL;
if (typenum >= 0 || typenum < -NUMBER_RECOGNIZED)
{
complaint (&symfile_complaints, _("Unknown builtin type %d"), typenum);
return builtin_type_error;
}
if (negative_types[-typenum] != NULL)
return negative_types[-typenum];
#if TARGET_CHAR_BIT != 8
#error This code wrong for TARGET_CHAR_BIT not 8
#endif
switch (-typenum)
{
case 1:
rettype = init_type (TYPE_CODE_INT, 4, 0, "int", objfile);
break;
case 2:
rettype = init_type (TYPE_CODE_INT, 1, 0, "char", objfile);
break;
case 3:
rettype = init_type (TYPE_CODE_INT, 2, 0, "short", objfile);
break;
case 4:
rettype = init_type (TYPE_CODE_INT, 4, 0, "long", objfile);
break;
case 5:
rettype = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED,
"unsigned char", objfile);
break;
case 6:
rettype = init_type (TYPE_CODE_INT, 1, 0, "signed char", objfile);
break;
case 7:
rettype = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED,
"unsigned short", objfile);
break;
case 8:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned int", objfile);
break;
case 9:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned", objfile);
case 10:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned long", objfile);
break;
case 11:
rettype = init_type (TYPE_CODE_VOID, 1, 0, "void", objfile);
break;
case 12:
rettype = init_type (TYPE_CODE_FLT, 4, 0, "float", objfile);
break;
case 13:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "double", objfile);
break;
case 14:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "long double", objfile);
break;
case 15:
rettype = init_type (TYPE_CODE_INT, 4, 0, "integer", objfile);
break;
case 16:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"boolean", objfile);
break;
case 17:
rettype = init_type (TYPE_CODE_FLT, 4, 0, "short real", objfile);
break;
case 18:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "real", objfile);
break;
case 19:
rettype = init_type (TYPE_CODE_ERROR, 0, 0, "stringptr", objfile);
break;
case 20:
rettype = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED,
"character", objfile);
break;
case 21:
rettype = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED,
"logical*1", objfile);
break;
case 22:
rettype = init_type (TYPE_CODE_BOOL, 2, TYPE_FLAG_UNSIGNED,
"logical*2", objfile);
break;
case 23:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"logical*4", objfile);
break;
case 24:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"logical", objfile);
break;
case 25:
rettype = init_type (TYPE_CODE_COMPLEX, 8, 0, "complex", objfile);
TYPE_TARGET_TYPE (rettype) = init_type (TYPE_CODE_FLT, 4, 0, "float",
NULL);
break;
case 26:
rettype = init_type (TYPE_CODE_COMPLEX, 16, 0, "double complex", objfile);
TYPE_TARGET_TYPE (rettype) = init_type (TYPE_CODE_FLT, 8, 0, "double",
NULL);
break;
case 27:
rettype = init_type (TYPE_CODE_INT, 1, 0, "integer*1", objfile);
break;
case 28:
rettype = init_type (TYPE_CODE_INT, 2, 0, "integer*2", objfile);
break;
case 29:
rettype = init_type (TYPE_CODE_INT, 4, 0, "integer*4", objfile);
break;
case 30:
rettype = init_type (TYPE_CODE_CHAR, 2, 0, "wchar", objfile);
break;
case 31:
rettype = init_type (TYPE_CODE_INT, 8, 0, "long long", objfile);
break;
case 32:
rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
"unsigned long long", objfile);
break;
case 33:
rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
"logical*8", objfile);
break;
case 34:
rettype = init_type (TYPE_CODE_INT, 8, 0, "integer*8", objfile);
break;
}
return rettype;
}
static int
read_member_functions (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
int nfn_fields = 0;
int length = 0;
int total_length = 0;
int i;
struct next_fnfield
{
struct next_fnfield *next;
struct fn_field fn_field;
}
*sublist;
struct type *look_ahead_type;
struct next_fnfieldlist *new_fnlist;
struct next_fnfield *new_sublist;
char *main_fn_name;
char *p;
while (**pp != ';')
{
p = *pp;
while (*p != ':')
{
p++;
}
if (p[1] != ':')
{
break;
}
sublist = NULL;
look_ahead_type = NULL;
length = 0;
new_fnlist = (struct next_fnfieldlist *)
xmalloc (sizeof (struct next_fnfieldlist));
make_cleanup (xfree, new_fnlist);
memset (new_fnlist, 0, sizeof (struct next_fnfieldlist));
if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && is_cplus_marker ((*pp)[2]))
{
static char opname[32] = "op$";
char *o = opname + 3;
*pp = p + 2;
STABS_CONTINUE (pp, objfile);
p = *pp;
while (*p != '.')
{
*o++ = *p++;
}
main_fn_name = savestring (opname, o - opname);
*pp = p + 1;
}
else
{
main_fn_name = savestring (*pp, p - *pp);
*pp = p + 2;
}
new_fnlist->fn_fieldlist.name =
obsavestring (main_fn_name, strlen (main_fn_name), &objfile->objfile_obstack);
do
{
new_sublist =
(struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
make_cleanup (xfree, new_sublist);
memset (new_sublist, 0, sizeof (struct next_fnfield));
if (look_ahead_type == NULL)
{
STABS_CONTINUE (pp, objfile);
new_sublist->fn_field.type = read_type (pp, objfile);
if (**pp != ':')
{
return 0;
}
}
else
{
new_sublist->fn_field.type = look_ahead_type;
look_ahead_type = NULL;
}
(*pp)++;
p = *pp;
while (*p != ';')
{
p++;
}
if (TYPE_STUB (new_sublist->fn_field.type))
{
if (!TYPE_DOMAIN_TYPE (new_sublist->fn_field.type))
TYPE_DOMAIN_TYPE (new_sublist->fn_field.type) = type;
new_sublist->fn_field.is_stub = 1;
}
new_sublist->fn_field.physname = obsavestring (*pp, p - *pp, &objfile->objfile_obstack);
*pp = p + 1;
switch (*(*pp)++)
{
case VISIBILITY_PRIVATE:
new_sublist->fn_field.is_private = 1;
break;
case VISIBILITY_PROTECTED:
new_sublist->fn_field.is_protected = 1;
break;
}
STABS_CONTINUE (pp, objfile);
switch (**pp)
{
case 'A':
new_sublist->fn_field.is_const = 0;
new_sublist->fn_field.is_volatile = 0;
(*pp)++;
break;
case 'B':
new_sublist->fn_field.is_const = 1;
new_sublist->fn_field.is_volatile = 0;
(*pp)++;
break;
case 'C':
new_sublist->fn_field.is_const = 0;
new_sublist->fn_field.is_volatile = 1;
(*pp)++;
break;
case 'D':
new_sublist->fn_field.is_const = 1;
new_sublist->fn_field.is_volatile = 1;
(*pp)++;
break;
case '*':
case '?':
case '.':
break;
default:
complaint (&symfile_complaints,
_("const/volatile indicator missing, got '%c'"), **pp);
break;
}
switch (*(*pp)++)
{
case '*':
{
int nbits;
new_sublist->fn_field.voffset =
(0x7fffffff & read_huge_number (pp, ';', &nbits, 0)) + 2;
if (nbits != 0)
return 0;
STABS_CONTINUE (pp, objfile);
if (**pp == ';' || **pp == '\0')
{
new_sublist->fn_field.fcontext = 0;
}
else
{
look_ahead_type = read_type (pp, objfile);
if (**pp == ':')
{
}
else
{
new_sublist->fn_field.fcontext = look_ahead_type;
if (**pp != ';')
{
return 0;
}
else
{
++*pp;
}
look_ahead_type = NULL;
}
}
break;
}
case '?':
{
int slen = strlen (main_fn_name);
new_sublist->fn_field.voffset = VOFFSET_STATIC;
if (!(strncmp (new_sublist->fn_field.physname,
main_fn_name, slen) == 0
&& new_sublist->fn_field.physname[slen] == '_'
&& new_sublist->fn_field.physname[slen + 1] == '_'))
{
new_sublist->fn_field.is_stub = 1;
}
break;
}
default:
complaint (&symfile_complaints,
_("member function type missing, got '%c'"), (*pp)[-1]);
case '.':
new_sublist->fn_field.voffset = 0;
new_sublist->fn_field.fcontext = 0;
break;
}
new_sublist->next = sublist;
sublist = new_sublist;
length++;
STABS_CONTINUE (pp, objfile);
}
while (**pp != ';' && **pp != '\0');
(*pp)++;
STABS_CONTINUE (pp, objfile);
if (strcmp (main_fn_name, "__base_ctor") == 0
|| strcmp (main_fn_name, "__base_dtor") == 0
|| strcmp (main_fn_name, "__deleting_dtor") == 0)
{
xfree (main_fn_name);
}
else
{
#if 0
int has_stub = 0;
int has_destructor = 0, has_other = 0;
int is_v3 = 0;
struct next_fnfield *tmp_sublist;
tmp_sublist = sublist;
while (tmp_sublist != NULL)
{
if (tmp_sublist->fn_field.is_stub)
has_stub = 1;
if (tmp_sublist->fn_field.physname[0] == '_'
&& tmp_sublist->fn_field.physname[1] == 'Z')
is_v3 = 1;
if (is_destructor_name (tmp_sublist->fn_field.physname))
has_destructor++;
else
has_other++;
tmp_sublist = tmp_sublist->next;
}
if (has_destructor && has_other)
{
struct next_fnfieldlist *destr_fnlist;
struct next_fnfield *last_sublist;
destr_fnlist = (struct next_fnfieldlist *)
xmalloc (sizeof (struct next_fnfieldlist));
make_cleanup (xfree, destr_fnlist);
memset (destr_fnlist, 0, sizeof (struct next_fnfieldlist));
destr_fnlist->fn_fieldlist.name
= obconcat (&objfile->objfile_obstack, "", "~",
new_fnlist->fn_fieldlist.name);
destr_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct fn_field) * has_destructor);
memset (destr_fnlist->fn_fieldlist.fn_fields, 0,
sizeof (struct fn_field) * has_destructor);
tmp_sublist = sublist;
last_sublist = NULL;
i = 0;
while (tmp_sublist != NULL)
{
if (!is_destructor_name (tmp_sublist->fn_field.physname))
{
tmp_sublist = tmp_sublist->next;
continue;
}
destr_fnlist->fn_fieldlist.fn_fields[i++]
= tmp_sublist->fn_field;
if (last_sublist)
last_sublist->next = tmp_sublist->next;
else
sublist = tmp_sublist->next;
last_sublist = tmp_sublist;
tmp_sublist = tmp_sublist->next;
}
destr_fnlist->fn_fieldlist.length = has_destructor;
destr_fnlist->next = fip->fnlist;
fip->fnlist = destr_fnlist;
nfn_fields++;
total_length += has_destructor;
length -= has_destructor;
}
else if (is_v3)
{
update_method_name_from_physname (&new_fnlist->fn_fieldlist.name,
sublist->fn_field.physname);
}
else if (has_destructor && new_fnlist->fn_fieldlist.name[0] != '~')
{
new_fnlist->fn_fieldlist.name =
concat ("~", main_fn_name, (char *)NULL);
xfree (main_fn_name);
}
else if (!has_stub)
{
char dem_opname[256];
int ret;
ret = cplus_demangle_opname (new_fnlist->fn_fieldlist.name,
dem_opname, DMGL_ANSI);
if (!ret)
ret = cplus_demangle_opname (new_fnlist->fn_fieldlist.name,
dem_opname, 0);
if (ret)
new_fnlist->fn_fieldlist.name
= obsavestring (dem_opname, strlen (dem_opname),
&objfile->objfile_obstack);
}
#endif
new_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct fn_field) * length);
memset (new_fnlist->fn_fieldlist.fn_fields, 0,
sizeof (struct fn_field) * length);
for (i = length; (i--, sublist); sublist = sublist->next)
{
new_fnlist->fn_fieldlist.fn_fields[i] = sublist->fn_field;
}
new_fnlist->fn_fieldlist.length = length;
new_fnlist->next = fip->fnlist;
fip->fnlist = new_fnlist;
nfn_fields++;
total_length += length;
}
}
if (nfn_fields)
{
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
memset (TYPE_FN_FIELDLISTS (type), 0,
sizeof (struct fn_fieldlist) * nfn_fields);
TYPE_NFN_FIELDS (type) = nfn_fields;
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
return 1;
}
static int
read_cpp_abbrev (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
char *p;
char *name;
char cpp_abbrev;
struct type *context;
p = *pp;
if (*++p == 'v')
{
name = NULL;
cpp_abbrev = *++p;
*pp = p + 1;
context = read_type (pp, objfile);
switch (cpp_abbrev)
{
case 'f':
name = type_name_no_tag (context);
if (name == NULL)
{
name = "";
}
fip->list->field.name =
obconcat (&objfile->objfile_obstack, vptr_name, name, "");
break;
case 'b':
name = type_name_no_tag (context);
if (name == NULL)
{
complaint (&symfile_complaints,
_("C++ abbreviated type name unknown at symtab pos %d"),
symnum);
name = "FOO";
}
fip->list->field.name =
obconcat (&objfile->objfile_obstack, vb_name, name, "");
break;
default:
invalid_cpp_abbrev_complaint (*pp);
fip->list->field.name =
obconcat (&objfile->objfile_obstack,
"INVALID_CPLUSPLUS_ABBREV", "", "");
break;
}
p = ++(*pp);
if (p[-1] != ':')
{
invalid_cpp_abbrev_complaint (*pp);
return 0;
}
fip->list->field.type = read_type (pp, objfile);
if (**pp == ',')
(*pp)++;
else
return 0;
{
int nbits;
FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ';', &nbits,
0);
if (nbits != 0)
return 0;
}
FIELD_BITSIZE (fip->list->field) = 0;
fip->list->visibility = VISIBILITY_PRIVATE;
}
else
{
invalid_cpp_abbrev_complaint (*pp);
return 0;
}
return 1;
}
static void
read_one_struct_field (struct field_info *fip, char **pp, char *p,
struct type *type, struct objfile *objfile)
{
fip->list->field.name =
obsavestring (*pp, p - *pp, &objfile->objfile_obstack);
*pp = p + 1;
if (**pp == '/')
{
(*pp)++;
fip->list->visibility = *(*pp)++;
}
else
{
fip->list->visibility = VISIBILITY_PUBLIC;
}
fip->list->field.type = read_type (pp, objfile);
if (**pp == ';')
++(*pp);
if (**pp == ':')
{
p = ++(*pp);
#if 0
if (**pp == '!')
{
fip->list->field.bitpos = (long) -2;
p = ++(*pp);
}
else
...;
#endif
while (*p != ';')
{
p++;
}
SET_FIELD_PHYSNAME (fip->list->field, obsavestring (*pp, p - *pp, &objfile->objfile_obstack));
*pp = p + 1;
return;
}
else if (**pp != ',')
{
stabs_general_complaint ("bad structure-type format");
return;
}
(*pp)++;
{
int nbits;
FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ',', &nbits, 0);
if (nbits != 0)
{
stabs_general_complaint ("bad structure-type format");
return;
}
FIELD_BITSIZE (fip->list->field) = read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
{
stabs_general_complaint ("bad structure-type format");
return;
}
}
if (FIELD_BITPOS (fip->list->field) == 0
&& FIELD_BITSIZE (fip->list->field) == 0)
{
fip->list->visibility = VISIBILITY_IGNORE;
}
else
{
adjust_field_bitsize (&fip->list->field);
}
}
static void
adjust_field_bitsize (struct field *field)
{
struct type *field_type = check_typedef (FIELD_TYPE (*field));
if (TYPE_CODE (field_type) != TYPE_CODE_UNDEF)
{
if (TYPE_CODE (field_type) != TYPE_CODE_INT
&& TYPE_CODE (field_type) != TYPE_CODE_RANGE
&& TYPE_CODE (field_type) != TYPE_CODE_BOOL
&& TYPE_CODE (field_type) != TYPE_CODE_ENUM)
{
FIELD_BITSIZE (*field) = 0;
}
if ((FIELD_BITSIZE (*field)
== TARGET_CHAR_BIT * TYPE_LENGTH (field_type)
|| (TYPE_CODE (field_type) == TYPE_CODE_ENUM
&& FIELD_BITSIZE (*field) == TARGET_INT_BIT)
)
&&
FIELD_BITPOS (*field) % 8 == 0)
{
FIELD_BITSIZE (*field) = 0;
}
}
}
static int
read_struct_fields (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
char *p;
struct nextfield *new;
p = *pp;
while (**pp != ';' && **pp != '\0')
{
STABS_CONTINUE (pp, objfile);
new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (xfree, new);
memset (new, 0, sizeof (struct nextfield));
new->next = fip->list;
fip->list = new;
p = *pp;
if (is_cplus_marker (p[0]) && p[1] != '_')
{
if (!read_cpp_abbrev (fip, pp, type, objfile))
return 0;
continue;
}
while (*p != ':' && *p != '\0')
{
p++;
}
if (*p == '\0')
return 0;
if (p[1] == ':')
{
break;
}
read_one_struct_field (fip, pp, p, type, objfile);
}
if (p[0] == ':' && p[1] == ':')
{
fip->list = fip->list->next;
}
return 1;
}
static int
read_baseclasses (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
int i;
struct nextfield *new;
if (**pp != '!')
{
return 1;
}
else
{
(*pp)++;
}
ALLOCATE_CPLUS_STRUCT_TYPE (type);
{
int nbits;
TYPE_N_BASECLASSES (type) = read_huge_number (pp, ',', &nbits, 0);
if (nbits != 0)
return 0;
}
#if 0
TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
#else
{
int num_bytes = B_BYTES (TYPE_N_BASECLASSES (type));
char *pointer;
pointer = (char *) TYPE_ALLOC (type, num_bytes);
TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
}
#endif
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
{
new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (xfree, new);
memset (new, 0, sizeof (struct nextfield));
new->next = fip->list;
fip->list = new;
FIELD_BITSIZE (new->field) = 0;
STABS_CONTINUE (pp, objfile);
switch (**pp)
{
case '0':
break;
case '1':
SET_TYPE_FIELD_VIRTUAL (type, i);
break;
default:
{
complaint (&symfile_complaints,
_("Unknown virtual character `%c' for baseclass"), **pp);
}
}
++(*pp);
new->visibility = *(*pp)++;
switch (new->visibility)
{
case VISIBILITY_PRIVATE:
case VISIBILITY_PROTECTED:
case VISIBILITY_PUBLIC:
break;
default:
{
complaint (&symfile_complaints,
_("Unknown visibility `%c' for baseclass"),
new->visibility);
new->visibility = VISIBILITY_PUBLIC;
}
}
{
int nbits;
FIELD_BITPOS (new->field) = read_huge_number (pp, ',', &nbits, 0);
if (nbits != 0)
return 0;
}
new->field.type = read_type (pp, objfile);
new->field.name = type_name_no_tag (new->field.type);
if (**pp == ';')
(*pp)++;
else
return 0;
}
return 1;
}
static int
read_tilde_fields (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
char *p;
STABS_CONTINUE (pp, objfile);
if (**pp == ';')
{
(*pp)++;
}
if (**pp == '~')
{
(*pp)++;
if (**pp == '=' || **pp == '+' || **pp == '-')
{
(*pp)++;
}
if (*(*pp)++ == '%')
{
struct type *t;
int i;
t = read_type (pp, objfile);
p = (*pp)++;
while (*p != '\0' && *p != ';')
{
p++;
}
if (*p == '\0')
{
return 0;
}
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
for (i = TYPE_NFIELDS (t) - 1;
i >= TYPE_N_BASECLASSES (t);
--i)
{
char *name = TYPE_FIELD_NAME (t, i);
if (!strncmp (name, vptr_name, sizeof (vptr_name) - 2)
&& is_cplus_marker (name[sizeof (vptr_name) - 2]))
{
TYPE_VPTR_FIELDNO (type) = i;
goto gotit;
}
}
complaint (&symfile_complaints,
_("virtual function table pointer not found when defining class `%s'"),
TYPE_NAME (type));
return 0;
}
else
{
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
}
gotit:
*pp = p + 1;
}
}
return 1;
}
static int
attach_fn_fields_to_type (struct field_info *fip, struct type *type)
{
int n;
for (n = TYPE_NFN_FIELDS (type);
fip->fnlist != NULL;
fip->fnlist = fip->fnlist->next)
{
--n;
TYPE_FN_FIELDLISTS (type)[n] = fip->fnlist->fn_fieldlist;
}
return 1;
}
static int
attach_fields_to_type (struct field_info *fip, struct type *type,
struct objfile *objfile)
{
int nfields = 0;
int non_public_fields = 0;
struct nextfield *scan;
for (scan = fip->list; scan != NULL; scan = scan->next)
{
nfields++;
if (scan->visibility != VISIBILITY_PUBLIC)
{
non_public_fields++;
}
}
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
TYPE_ALLOC (type, sizeof (struct field) * nfields);
memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
if (non_public_fields)
{
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FIELD_PRIVATE_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
TYPE_FIELD_PROTECTED_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
TYPE_FIELD_IGNORE_BITS (type) =
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
}
while (nfields-- > 0)
{
TYPE_FIELD (type, nfields) = fip->list->field;
switch (fip->list->visibility)
{
case VISIBILITY_PRIVATE:
SET_TYPE_FIELD_PRIVATE (type, nfields);
break;
case VISIBILITY_PROTECTED:
SET_TYPE_FIELD_PROTECTED (type, nfields);
break;
case VISIBILITY_IGNORE:
SET_TYPE_FIELD_IGNORE (type, nfields);
break;
case VISIBILITY_PUBLIC:
break;
default:
{
complaint (&symfile_complaints, _("Unknown visibility `%c' for field"),
fip->list->visibility);
}
break;
}
if (TYPE_CODE (FIELD_TYPE (fip->list->field)) == TYPE_CODE_UNDEF
|| (TYPE_CODE (FIELD_TYPE (fip->list->field)) == TYPE_CODE_TYPEDEF
&& (TYPE_TARGET_TYPE (FIELD_TYPE (fip->list->field)) == NULL
|| TYPE_CODE (TYPE_TARGET_TYPE (FIELD_TYPE (fip->list->field))) == TYPE_CODE_UNDEF)))
add_undefined_field (&(TYPE_FIELD (type, nfields)));
fip->list = fip->list->next;
}
return 1;
}
static void
complain_about_struct_wipeout (struct type *type)
{
char *name = "";
char *kind = "";
if (TYPE_TAG_NAME (type))
{
name = TYPE_TAG_NAME (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_STRUCT: kind = "struct "; break;
case TYPE_CODE_UNION: kind = "union "; break;
case TYPE_CODE_ENUM: kind = "enum "; break;
default: kind = "";
}
}
else if (TYPE_NAME (type))
{
name = TYPE_NAME (type);
kind = "";
}
else
{
name = "<unknown>";
kind = "";
}
complaint (&symfile_complaints,
_("struct/union type gets multiply defined: %s%s"), kind, name);
}
static struct type *
read_struct_type (char **pp, struct type *type, enum type_code type_code,
struct objfile *objfile)
{
struct cleanup *back_to;
struct field_info fi;
fi.list = NULL;
fi.fnlist = NULL;
if (! (TYPE_CODE (type) == TYPE_CODE_UNDEF
|| TYPE_STUB (type)))
{
complain_about_struct_wipeout (type);
}
back_to = make_cleanup (null_cleanup, 0);
INIT_CPLUS_SPECIFIC (type);
TYPE_CODE (type) = type_code;
TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
{
int nbits;
TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
}
if (!read_baseclasses (&fi, pp, type, objfile)
|| !read_struct_fields (&fi, pp, type, objfile)
|| !attach_fields_to_type (&fi, type, objfile)
|| !read_member_functions (&fi, pp, type, objfile)
|| !attach_fn_fields_to_type (&fi, type)
|| !read_tilde_fields (&fi, pp, type, objfile))
{
type = error_type (pp, objfile);
}
do_cleanups (back_to);
return (type);
}
static struct type *
read_array_type (char **pp, struct type *type,
struct objfile *objfile)
{
struct type *index_type, *element_type, *range_type;
int lower, upper;
int adjustable = 0;
int nbits;
{
index_type = read_type (pp, objfile);
if (**pp != ';')
return error_type (pp, objfile);
++*pp;
}
if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
{
(*pp)++;
adjustable = 1;
}
lower = read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
{
(*pp)++;
adjustable = 1;
}
upper = read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
element_type = read_type (pp, objfile);
if (adjustable)
{
lower = 0;
upper = -1;
}
range_type =
create_range_type ((struct type *) NULL, index_type, lower, upper);
type = create_array_type (type, element_type, range_type);
return type;
}
static struct type *
read_enum_type (char **pp, struct type *type,
struct objfile *objfile)
{
char *p;
char *name;
long n;
struct symbol *sym;
int nsyms = 0;
struct pending **symlist;
struct pending *osyms, *syms;
int o_nsyms;
int nbits;
int unsigned_enum = 1;
#if 0
if (within_function)
symlist = &local_symbols;
else
#endif
symlist = &file_symbols;
osyms = *symlist;
o_nsyms = osyms ? osyms->nsyms : 0;
if (**pp == '-')
{
while (**pp != ':')
(*pp)++;
(*pp)++;
}
while (**pp && **pp != ';' && **pp != ',')
{
STABS_CONTINUE (pp, objfile);
p = *pp;
while (*p != ':')
p++;
name = obsavestring (*pp, p - *pp, &objfile->objfile_obstack);
*pp = p + 1;
n = read_huge_number (pp, ',', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
DEPRECATED_SYMBOL_NAME (sym) = name;
SYMBOL_LANGUAGE (sym) = current_subfile->language;
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_VALUE (sym) = n;
if (n < 0)
unsigned_enum = 0;
add_symbol_to_list (sym, symlist);
nsyms++;
}
if (**pp == ';')
(*pp)++;
TYPE_LENGTH (type) = TARGET_INT_BIT / HOST_CHAR_BIT;
TYPE_CODE (type) = TYPE_CODE_ENUM;
TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
if (unsigned_enum)
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
TYPE_NFIELDS (type) = nsyms;
TYPE_FIELDS (type) = (struct field *)
TYPE_ALLOC (type, sizeof (struct field) * nsyms);
memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nsyms);
for (syms = *symlist, n = nsyms - 1; syms; syms = syms->next)
{
int last = syms == osyms ? o_nsyms : 0;
int j = syms->nsyms;
for (; --j >= last; --n)
{
struct symbol *xsym = syms->symbol[j];
SYMBOL_TYPE (xsym) = type;
TYPE_FIELD_NAME (type, n) = DEPRECATED_SYMBOL_NAME (xsym);
TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
TYPE_FIELD_BITSIZE (type, n) = 0;
}
if (syms == osyms)
break;
}
return type;
}
static struct type *
read_sun_builtin_type (char **pp, int typenums[2], struct objfile *objfile)
{
int type_bits;
int nbits;
int signed_type;
enum type_code code = TYPE_CODE_INT;
switch (**pp)
{
case 's':
signed_type = 1;
break;
case 'u':
signed_type = 0;
break;
default:
return error_type (pp, objfile);
}
(*pp)++;
if (**pp == 'c')
(*pp)++;
else if (**pp == 'b')
{
code = TYPE_CODE_BOOL;
(*pp)++;
}
read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
type_bits = read_huge_number (pp, 0, &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
if (**pp == ';')
++(*pp);
if (type_bits == 0)
return init_type (TYPE_CODE_VOID, 1,
signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *) NULL,
objfile);
else
return init_type (code,
type_bits / TARGET_CHAR_BIT,
signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *) NULL,
objfile);
}
static struct type *
read_sun_floating_type (char **pp, int typenums[2], struct objfile *objfile)
{
int nbits;
int details;
int nbytes;
struct type *rettype;
details = read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
nbytes = read_huge_number (pp, ';', &nbits, 0);
if (nbits != 0)
return error_type (pp, objfile);
if (details == NF_COMPLEX || details == NF_COMPLEX16
|| details == NF_COMPLEX32)
{
rettype = init_type (TYPE_CODE_COMPLEX, nbytes, 0, NULL, objfile);
TYPE_TARGET_TYPE (rettype)
= init_type (TYPE_CODE_FLT, nbytes / 2, 0, NULL, objfile);
return rettype;
}
return init_type (TYPE_CODE_FLT, nbytes, 0, NULL, objfile);
}
static long
read_huge_number (char **pp, int end, int *bits, int twos_complement_bits)
{
char *p = *pp;
int sign = 1;
int sign_bit;
long n = 0;
long sn = 0;
int radix = 10;
char overflow = 0;
int nbits = 0;
int c;
long upper_limit;
int twos_complement_representation = radix == 8 && twos_complement_bits > 0;
if (*p == '-')
{
sign = -1;
p++;
}
if (*p == '0')
{
radix = 8;
p++;
}
upper_limit = LONG_MAX / radix;
while ((c = *p++) >= '0' && c < ('0' + radix))
{
if (n <= upper_limit)
{
if (twos_complement_representation)
{
if (sn == 0)
{
sign_bit = (twos_complement_bits % 3 + 2) % 3;
sn = c - '0' - ((2 * (c - '0')) | (2 << sign_bit));
}
else
{
sn *= radix;
sn += c - '0';
}
if (sn < 0)
n = -sn;
}
else
{
n *= radix;
n += c - '0';
}
}
else
overflow = 1;
if (radix == 8)
{
if (nbits == 0)
{
if (c == '0')
;
else if (c == '1')
nbits = 1;
else if (c == '2' || c == '3')
nbits = 2;
else
nbits = 3;
}
else
nbits += 3;
}
}
if (end)
{
if (c && c != end)
{
if (bits != NULL)
*bits = -1;
return 0;
}
}
else
--p;
*pp = p;
if (overflow)
{
if (nbits == 0)
{
if (bits != NULL)
*bits = -1;
return 0;
}
if (sign == -1)
++nbits;
if (bits)
*bits = nbits;
}
else
{
if (bits)
*bits = 0;
if (twos_complement_representation)
return sn;
else
return n * sign;
}
return 0;
}
static struct type *
read_range_type (char **pp, int typenums[2], int type_size,
struct objfile *objfile)
{
char *orig_pp = *pp;
int rangenums[2];
long n2, n3;
int n2bits, n3bits;
int self_subrange;
struct type *result_type;
struct type *index_type = NULL;
if (read_type_number (pp, rangenums) != 0)
return error_type (pp, objfile);
self_subrange = (rangenums[0] == typenums[0] &&
rangenums[1] == typenums[1]);
if (**pp == '=')
{
*pp = orig_pp;
index_type = read_type (pp, objfile);
}
if (**pp == ';')
(*pp)++;
n2 = read_huge_number (pp, ';', &n2bits, type_size);
n3 = read_huge_number (pp, ';', &n3bits, type_size);
if (n2bits == -1 || n3bits == -1)
return error_type (pp, objfile);
if (index_type)
goto handle_true_range;
if (n2bits != 0 || n3bits != 0)
{
char got_signed = 0;
char got_unsigned = 0;
int nbits = 0;
if (n2bits <= type_size && n3bits <= type_size)
{
if (n2bits == type_size && n2bits > n3bits)
got_signed = 1;
else
got_unsigned = 1;
nbits = type_size;
}
else if ((n2bits == 0 && n2 == 0) && n3bits != 0)
{
got_unsigned = 1;
nbits = n3bits;
}
else if ((n2bits != 0 && n3bits != 0 && n2bits == n3bits + 1)
|| (n2bits != 0 && n3bits == 0
&& (n2bits == sizeof (long) * HOST_CHAR_BIT)
&& n3 == LONG_MAX))
{
got_signed = 1;
nbits = n2bits;
}
if (got_signed || got_unsigned)
{
return init_type (TYPE_CODE_INT, nbits / TARGET_CHAR_BIT,
got_unsigned ? TYPE_FLAG_UNSIGNED : 0, NULL,
objfile);
}
else
return error_type (pp, objfile);
}
if (self_subrange && n2 == 0 && n3 == 0)
return init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile);
if (n3 == 0 && n2 > 0)
{
struct type *float_type
= init_type (TYPE_CODE_FLT, n2, 0, NULL, objfile);
if (self_subrange)
{
struct type *complex_type =
init_type (TYPE_CODE_COMPLEX, 2 * n2, 0, NULL, objfile);
TYPE_TARGET_TYPE (complex_type) = float_type;
return complex_type;
}
else
return float_type;
}
else if (n2 == 0 && n3 == -1)
{
return init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, NULL, objfile);
}
else if (self_subrange && n2 == 0 && n3 == 127)
return init_type (TYPE_CODE_INT, 1, TYPE_FLAG_NOSIGN, NULL, objfile);
else if (n2 == 0)
{
if (n3 < 0)
return init_type (TYPE_CODE_INT, -n3, TYPE_FLAG_UNSIGNED,
NULL, objfile);
{
int bytes;
unsigned long bits;
bits = n3;
for (bytes = 0; (bits & 0xff) == 0xff; bytes++)
bits >>= 8;
if (bits == 0
&& ((bytes - 1) & bytes) == 0)
return init_type (TYPE_CODE_INT, bytes, TYPE_FLAG_UNSIGNED, NULL,
objfile);
}
}
else if (n3 == 0 && n2 < 0
&& (self_subrange
|| n2 == -TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT))
return init_type (TYPE_CODE_INT, -n2, 0, NULL, objfile);
else if (n2 == -n3 - 1)
{
if (n3 == 0x7f)
return init_type (TYPE_CODE_INT, 1, 0, NULL, objfile);
if (n3 == 0x7fff)
return init_type (TYPE_CODE_INT, 2, 0, NULL, objfile);
if (n3 == 0x7fffffff)
return init_type (TYPE_CODE_INT, 4, 0, NULL, objfile);
}
handle_true_range:
if (self_subrange)
index_type = builtin_type_int;
else
index_type = *dbx_lookup_type (rangenums, objfile);
if (index_type == NULL)
{
static struct type *range_type_index;
complaint (&symfile_complaints,
_("base type %d of range type is not defined"), rangenums[1]);
if (range_type_index == NULL)
range_type_index =
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
0, "range type index type", NULL);
index_type = range_type_index;
}
result_type = create_range_type ((struct type *) NULL, index_type, n2, n3);
return (result_type);
}
static struct field *
read_args (char **pp, int end, struct objfile *objfile, int *nargsp,
int *varargsp)
{
unsigned int tsize = 64;
struct type *tbuf[64];
struct type **talloc = NULL;
struct type **tcur = tbuf;
struct field *rval = NULL;
unsigned int n = 0;
unsigned int i;
for (;;)
{
struct type *type;
if (**pp == end)
{
(*pp)++;
break;
}
if (**pp != ',')
{
xfree (talloc);
return (struct field *) -1;
}
(*pp)++;
STABS_CONTINUE (pp, objfile);
type = read_type (pp, objfile);
if (type == NULL)
{
xfree (talloc);
return (struct field *) -1;
}
if (n >= tsize)
{
tsize *= 2;
talloc = (struct type **) xrealloc (talloc, tsize * sizeof (struct type *));
tcur = talloc;
}
tcur[n++] = type;
}
if ((n > 0) && (TYPE_CODE (tcur[n - 1]) != TYPE_CODE_VOID))
{
*varargsp = 1;
}
else
{
n--;
*varargsp = 0;
}
*nargsp = n;
rval = (struct field *) obstack_alloc
(&objfile->objfile_obstack, n * sizeof (struct field));
memset (rval, 0, n * sizeof (struct field));
for (i = 0; i < n; i++)
rval[i].type = tcur[i];
xfree (talloc);
return rval;
}
static struct pending *common_block;
static int common_block_i;
static char *common_block_name;
void
common_block_start (char *name, struct objfile *objfile)
{
if (common_block_name != NULL)
{
complaint (&symfile_complaints,
_("Invalid symbol data: common block within common block"));
}
common_block = local_symbols;
common_block_i = local_symbols ? local_symbols->nsyms : 0;
common_block_name = obsavestring (name, strlen (name),
&objfile->objfile_obstack);
}
void
common_block_end (struct objfile *objfile)
{
int i;
struct symbol *sym;
struct pending *new = 0;
struct pending *next;
int j;
if (common_block_name == NULL)
{
complaint (&symfile_complaints, _("ECOMM symbol unmatched by BCOMM"));
return;
}
sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
DEPRECATED_SYMBOL_NAME (sym) = common_block_name;
SYMBOL_CLASS (sym) = LOC_BLOCK;
for (next = local_symbols;
next != NULL && next != common_block;
next = next->next)
{
for (j = 0; j < next->nsyms; j++)
add_symbol_to_list (next->symbol[j], &new);
}
if (common_block != NULL)
for (j = common_block_i; j < common_block->nsyms; j++)
add_symbol_to_list (common_block->symbol[j], &new);
SYMBOL_TYPE (sym) = (struct type *) new;
i = hashname (DEPRECATED_SYMBOL_NAME (sym));
SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
global_sym_chain[i] = sym;
common_block_name = NULL;
}
static void
fix_common_block (struct symbol *sym, int valu)
{
struct pending *next = (struct pending *) SYMBOL_TYPE (sym);
for (; next; next = next->next)
{
int j;
for (j = next->nsyms - 1; j >= 0; j--)
SYMBOL_VALUE_ADDRESS (next->symbol[j]) += valu;
}
}
static void
add_undefined_field (struct field *field)
{
if (undef_fields_length == undef_fields_allocated)
{
undef_fields_allocated *= 2;
undef_fields = (struct field **)
xrealloc ((char *) undef_fields,
undef_fields_allocated * sizeof (struct field *));
}
undef_fields[undef_fields_length++] = field;
}
void
cleanup_undefined_fields (void)
{
struct field **field;
for (field = undef_fields; field < undef_fields + undef_fields_length; field++)
{
adjust_field_bitsize (*field);
}
undef_fields_length = 0;
}
static void
add_undefined_type (struct type *type)
{
if (undef_types_length == undef_types_allocated)
{
undef_types_allocated *= 2;
undef_types = (struct type **)
xrealloc ((char *) undef_types,
undef_types_allocated * sizeof (struct type *));
}
undef_types[undef_types_length++] = type;
}
void
cleanup_undefined_types (void)
{
struct type **type;
for (type = undef_types; type < undef_types + undef_types_length; type++)
{
switch (TYPE_CODE (*type))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_ENUM:
{
if (TYPE_STUB (*type))
{
struct pending *ppt;
int i;
char *typename = TYPE_TAG_NAME (*type);
if (typename == NULL)
{
complaint (&symfile_complaints, _("need a type name"));
break;
}
for (ppt = file_symbols; ppt; ppt = ppt->next)
{
for (i = 0; i < ppt->nsyms; i++)
{
struct symbol *sym = ppt->symbol[i];
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
&& SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& (TYPE_CODE (SYMBOL_TYPE (sym)) ==
TYPE_CODE (*type))
&& (TYPE_INSTANCE_FLAGS (SYMBOL_TYPE (sym)) ==
TYPE_INSTANCE_FLAGS (*type))
&& strcmp (DEPRECATED_SYMBOL_NAME (sym), typename) == 0)
replace_type (*type, SYMBOL_TYPE (sym));
}
}
}
}
break;
default:
{
if (TYPE_CODE (*type) == TYPE_CODE_UNDEF
|| TYPE_CODE (*type) == TYPE_CODE_ERROR)
{
complaint (&symfile_complaints,
"forward-referenced types left unresolved, "
"type code %d: name: %s target: %s",
TYPE_CODE (*type),
TYPE_NAME (*type) ? TYPE_NAME (*type) : "NULL",
(TYPE_TARGET_TYPE (*type)
&& TYPE_NAME (TYPE_TARGET_TYPE (*type)))
? TYPE_NAME (TYPE_TARGET_TYPE(*type))
: "NULL");
}
}
break;
}
}
undef_types_length = 0;
}
void
scan_file_globals (struct objfile *objfile)
{
int hash;
struct minimal_symbol *msymbol;
struct symbol *sym, *prev;
struct objfile *resolve_objfile;
resolve_objfile = objfile;
while (1)
{
for (hash = 0; hash < HASHSIZE; hash++)
{
if (global_sym_chain[hash])
break;
}
if (hash >= HASHSIZE)
return;
for (msymbol = resolve_objfile->msymbols;
msymbol && DEPRECATED_SYMBOL_NAME (msymbol) != NULL;
msymbol++)
{
QUIT;
switch (MSYMBOL_TYPE (msymbol))
{
case mst_file_text:
case mst_file_data:
case mst_file_bss:
continue;
default:
break;
}
prev = NULL;
hash = hashname (DEPRECATED_SYMBOL_NAME (msymbol));
for (sym = global_sym_chain[hash]; sym;)
{
if (DEPRECATED_SYMBOL_NAME (msymbol)[0] == DEPRECATED_SYMBOL_NAME (sym)[0] &&
strcmp (DEPRECATED_SYMBOL_NAME (msymbol) + 1, DEPRECATED_SYMBOL_NAME (sym) + 1) == 0)
{
if (prev)
{
SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
}
else
{
global_sym_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
}
if (sym)
{
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
fix_common_block (sym,
SYMBOL_VALUE_ADDRESS (msymbol));
}
else
{
SYMBOL_VALUE_ADDRESS (sym)
= SYMBOL_VALUE_ADDRESS (msymbol);
}
SYMBOL_SECTION (sym) = SYMBOL_SECTION (msymbol);
}
if (prev)
{
sym = SYMBOL_VALUE_CHAIN (prev);
}
else
{
sym = global_sym_chain[hash];
}
}
else
{
prev = sym;
sym = SYMBOL_VALUE_CHAIN (sym);
}
}
}
if (symfile_objfile && objfile != symfile_objfile &&
resolve_objfile == objfile)
{
resolve_objfile = symfile_objfile;
}
else
break;
}
for (hash = 0; hash < HASHSIZE; hash++)
{
sym = global_sym_chain[hash];
while (sym)
{
prev = sym;
sym = SYMBOL_VALUE_CHAIN (sym);
SYMBOL_VALUE_ADDRESS (prev) = 0;
if (SYMBOL_CLASS (prev) == LOC_STATIC)
SYMBOL_CLASS (prev) = LOC_UNRESOLVED;
else
complaint (&symfile_complaints,
_("%s: common block `%s' from global_sym_chain unresolved"),
objfile->name, DEPRECATED_SYMBOL_NAME (prev));
}
}
memset (global_sym_chain, 0, sizeof (global_sym_chain));
}
void
stabsread_init (void)
{
}
void
stabsread_new_init (void)
{
memset (global_sym_chain, 0, sizeof (global_sym_chain));
}
void
start_stabs (void)
{
global_stabs = NULL;
n_this_object_header_files = 1;
type_vector_length = 0;
type_vector = (struct type **) 0;
common_block_name = NULL;
}
void
end_stabs (void)
{
if (type_vector)
{
xfree (type_vector);
}
type_vector = 0;
type_vector_length = 0;
previous_stab_code = 0;
}
void
finish_global_stabs (struct objfile *objfile)
{
if (global_stabs)
{
patch_block_stabs (global_symbols, global_stabs, objfile);
xfree (global_stabs);
global_stabs = NULL;
}
}
char *
find_name_end (char *name)
{
char *s = name;
char *first_colon, *first_lbrac, *first_rbrac;
#if 1
first_colon = strchr (name, ':');
if (first_colon == NULL)
return NULL;
#else
first_colon = name;
while (1)
{
first_colon = strchr (first_colon, ':');
if (first_colon == NULL)
return NULL;
else if (first_colon[1] != ':')
break;
else
first_colon += 2;
}
#endif
first_lbrac = NULL;
for (s = name; s < first_colon; s++)
{
if (*s == '[')
{
first_lbrac = s;
break;
}
}
if (first_lbrac == NULL
|| (first_lbrac == name
|| (first_lbrac[-1] != '-'
&& first_lbrac[-1] != '+')))
return first_colon;
else
{
first_rbrac = strchr (name, ']');
if (first_rbrac == NULL)
error ("invalid symbol name \"%s\"", name);
return strchr (first_rbrac, ':');
}
}
void
_initialize_stabsread (void)
{
undef_types_allocated = 20;
undef_types_length = 0;
undef_types = (struct type **)
xmalloc (undef_types_allocated * sizeof (struct type *));
undef_fields_allocated = 20;
undef_fields_length = 0;
undef_fields = (struct field **)
xmalloc (undef_fields_allocated * sizeof (struct field *));
}