#include <limits.h>
#include "defs.h"
#include "gdb_string.h"
#include "bfd.h"
#include "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 <ctype.h>
#define EXTERN
#include "stabsread.h"
#undef EXTERN
extern void _initialize_stabsread (void);
#define MINUS_LONG_MIN (((unsigned long) (- (LONG_MAX + LONG_MIN))) + LONG_MAX)
#define UENUM_MAX UINT_MAX
#define UENUM_MIN UINT_MIN
#define ENUM_MAX INT_MAX
#define ENUM_MIN INT_MIN
#define MINUS_ENUM_MIN (((unsigned long) (- (ENUM_MAX + ENUM_MIN))) + ENUM_MAX)
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 char *get_substring (char **, int);
static struct type *dbx_alloc_type (int[2], struct objfile *);
static long read_huge_number (char **, int, int *);
static void read_huge_number_raw (char **pp, int end, int *bits,
int *sign, unsigned long *data);
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_range_type (char **, int[2], 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);
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 *,
struct objfile *);
static struct type *read_array_type (char **, struct type *,
struct objfile *);
static struct type **read_args (char **, int, struct objfile *);
static int
read_cpp_abbrev (struct field_info *, char **, struct type *,
struct objfile *);
static int
copy_cfront_struct_fields (struct field_info *, struct type *,
struct objfile *);
static char *get_cfront_method_physname (char *);
static int
read_cfront_baseclasses (struct field_info *, char **,
struct type *, struct objfile *);
static int
read_cfront_static_fields (struct field_info *, char **,
struct type *, struct objfile *);
static int
read_cfront_member_functions (struct field_info *, char **,
struct type *, struct objfile *);
static void
add_live_range (struct objfile *, struct symbol *, CORE_ADDR, CORE_ADDR);
static int resolve_live_range (struct objfile *, struct symbol *, char *);
static int process_reference (char **string);
static CORE_ADDR ref_search_value (int refnum);
static int
resolve_symbol_reference (struct objfile *, struct symbol *, char *);
void stabsread_clear_cache (void);
static const char vptr_name[] =
{'_', 'v', 'p', 't', 'r', CPLUS_MARKER, '\0'};
static const char vb_name[] =
{'_', 'v', 'b', CPLUS_MARKER, '\0'};
#if !defined (BELIEVE_PCC_PROMOTION)
#define BELIEVE_PCC_PROMOTION 0
#endif
#if !defined (BELIEVE_PCC_PROMOTION_TYPE)
#define BELIEVE_PCC_PROMOTION_TYPE 0
#endif
static struct complaint invalid_cpp_abbrev_complaint =
{"invalid C++ abbreviation `%s'", 0, 0};
static struct complaint invalid_cpp_type_complaint =
{"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
static struct complaint member_fn_complaint =
{"member function type missing, got '%c'", 0, 0};
static struct complaint const_vol_complaint =
{"const/volatile indicator missing, got '%c'", 0, 0};
static struct complaint error_type_complaint =
{"debug info mismatch between compiler and debugger", 0, 0};
static struct complaint invalid_member_complaint =
{"invalid (minimal) member type data format at symtab pos %d.", 0, 0};
static struct complaint range_type_base_complaint =
{"base type %d of range type is not defined", 0, 0};
static struct complaint reg_value_complaint =
{"register number %d too large (max %d) in symbol %s", 0, 0};
static struct complaint vtbl_notfound_complaint =
{"virtual function table pointer not found when defining class `%s'", 0, 0};
static struct complaint unrecognized_cplus_name_complaint =
{"Unknown C++ symbol name `%s'", 0, 0};
static struct complaint rs6000_builtin_complaint =
{"Unknown builtin type %d", 0, 0};
static struct complaint unresolved_sym_chain_complaint =
{"%s: common block `%s' from global_sym_chain unresolved", 0, 0};
static struct complaint stabs_general_complaint =
{"%s", 0, 0};
static struct complaint lrs_general_complaint =
{"%s", 0, 0};
static struct type **undef_types;
static int undef_types_allocated;
static int undef_types_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)
static struct type **os9k_type_vector[] =
{
0,
&builtin_type_int,
&builtin_type_char,
&builtin_type_long,
&builtin_type_short,
&builtin_type_unsigned_char,
&builtin_type_unsigned_short,
&builtin_type_unsigned_long,
&builtin_type_unsigned_int,
&builtin_type_float,
&builtin_type_double,
&builtin_type_void,
&builtin_type_long_double
};
static void os9k_init_type_vector (struct type **);
static void
os9k_init_type_vector (struct type **tv)
{
unsigned int i;
for (i = 0; i < sizeof (os9k_type_vector) / sizeof (struct type **); i++)
tv[i] = (os9k_type_vector[i] == 0 ? 0 : *(os9k_type_vector[i]));
}
struct type **
dbx_lookup_type (int typenums[2])
{
register int filenum = typenums[0];
register int index = typenums[1];
unsigned old_len;
register int real_filenum;
register struct header_file *f;
int f_orig_length;
if (filenum == -1)
return 0;
if (filenum < 0 || filenum >= n_this_object_header_files)
{
static struct complaint msg =
{"\
Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
0, 0};
complain (&msg, filenum, index, symnum);
goto error_return;
}
if (filenum == 0)
{
if (index < 0)
{
static struct type *temp_type;
temp_type = rs6000_builtin_type (index);
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 *));
if (os9k_stabs)
os9k_init_type_vector (type_vector);
}
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 struct type *
dbx_alloc_type (int typenums[2], struct objfile *objfile)
{
register struct type **type_addr;
if (typenums[0] == -1)
{
return (alloc_type (objfile));
}
type_addr = dbx_lookup_type (typenums);
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->symbol_obstack,
sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
SYMBOL_NAME (sym) =
obsavestring (name, pp - name, &objfile->symbol_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 (register char **pp, register int *typenums)
{
int nbits;
if (**pp == '(')
{
(*pp)++;
typenums[0] = read_huge_number (pp, ',', &nbits);
if (nbits != 0)
return -1;
typenums[1] = read_huge_number (pp, ')', &nbits);
if (nbits != 0)
return -1;
}
else
{
typenums[0] = 0;
typenums[1] = read_huge_number (pp, 0, &nbits);
if (nbits != 0)
return -1;
}
return 0;
}
#define VISIBILITY_PRIVATE '0'
#define VISIBILITY_PROTECTED '1'
#define VISIBILITY_PUBLIC '2'
#define VISIBILITY_IGNORE '9'
#define CFRONT_VISIBILITY_PRIVATE '2'
#define CFRONT_VISIBILITY_PUBLIC '1'
static char *
get_substring (char **p, int c)
{
char *str;
str = *p;
*p = strchr (*p, c);
if (*p)
{
**p = 0;
(*p)++;
}
else
str = 0;
return str;
}
static char *
get_cfront_method_physname (char *fname)
{
int len = 0;
char *p = fname;
if (*p == '_' && *(p + 1) == '_')
p += 2;
while (p && (unsigned) ((p + 1) - fname) < strlen (fname) && *(p + 1) != '_')
p = strchr (p, '_');
if (!(p && *p == '_' && *(p + 1) == '_'))
error ("Invalid mangled function name %s", fname);
p += 2;
while (isdigit (*p))
{
len = len * 10 + (*p - '0');
p++;
}
p += len;
return p;
}
static int
read_cfront_baseclasses (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
static struct complaint msg_unknown =
{"\
Unsupported token in stabs string %s.\n",
0, 0};
static struct complaint msg_notfound =
{"\
Unable to find base type for %s.\n",
0, 0};
int bnum = 0;
char *p;
int i;
struct nextfield *new;
if (**pp == ';')
{
++(*pp);
return 1;
}
for (p = *pp; p && *p && *p != ';'; p++)
{
if (*p == ' ')
bnum++;
}
bnum++;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_N_BASECLASSES (type) = bnum;
{
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;
}
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);
if (**pp == 'v')
{
SET_TYPE_FIELD_VIRTUAL (type, i);
++(*pp);
}
switch (*(*pp)++)
{
case CFRONT_VISIBILITY_PRIVATE:
new->visibility = VISIBILITY_PRIVATE;
break;
case CFRONT_VISIBILITY_PUBLIC:
new->visibility = VISIBILITY_PUBLIC;
break;
default:
{
static struct complaint msg =
{
"Unknown visibility `%c' for baseclass", 0, 0};
complain (&msg, new->visibility);
new->visibility = VISIBILITY_PUBLIC;
}
}
if (**pp != '@')
{
complain (&msg_unknown, *pp);
return 1;
}
++(*pp);
FIELD_BITPOS (new->field) = 0;
{
char *bname;
struct symbol *bsym;
char *p1, *p2;
p1 = strchr (*pp, ' ');
p2 = strchr (*pp, ';');
if (p1 < p2)
bname = get_substring (pp, ' ');
else
bname = get_substring (pp, ';');
if (!bname || !*bname)
{
complain (&msg_unknown, *pp);
return 1;
}
bsym = lookup_symbol (bname, 0, STRUCT_NAMESPACE, 0, 0);
if (bsym)
{
new->field.type = SYMBOL_TYPE (bsym);
new->field.name = type_name_no_tag (new->field.type);
}
else
{
complain (&msg_notfound, *pp);
return 1;
}
}
}
return 1;
}
static int
read_cfront_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 *fname;
struct symbol *ref_func = 0;
STABS_CONTINUE (pp, objfile);
while (**pp != ';' && (fname = get_substring (pp, ' '), fname))
{
int is_static = 0;
int sublist_count = 0;
char *pname;
if (fname[0] == '*')
{
is_static = 1;
sublist_count++;
fname++;
}
ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0);
if (!ref_func)
{
static struct complaint msg =
{"\
Unable to find function symbol for %s\n",
0, 0};
complain (&msg, fname);
continue;
}
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));
{
char *dem, *dem_p, *dem_args;
int dem_len;
dem = cplus_demangle (fname, DMGL_ANSI | DMGL_PARAMS);
if (dem != NULL)
{
dem_p = strrchr (dem, ':');
if (dem_p != 0 && *(dem_p - 1) == ':')
dem_p++;
dem_args = strchr (dem_p, '(');
if (dem_args == NULL)
dem_len = strlen (dem_p);
else
dem_len = dem_args - dem_p;
main_fn_name =
obsavestring (dem_p, dem_len, &objfile->type_obstack);
}
else
{
main_fn_name =
obsavestring (fname, strlen (fname), &objfile->type_obstack);
}
}
new_fnlist->fn_fieldlist.name = main_fn_name;
new_sublist =
(struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
make_cleanup (xfree, new_sublist);
memset (new_sublist, 0, sizeof (struct next_fnfield));
new_sublist->fn_field.type = SYMBOL_TYPE (ref_func);
TYPE_FLAGS (new_sublist->fn_field.type) |= TYPE_FLAG_STUB;
TYPE_CODE (new_sublist->fn_field.type) = TYPE_CODE_METHOD;
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;
}
pname = get_cfront_method_physname (fname);
new_sublist->fn_field.physname = savestring (pname, strlen (pname));
new_sublist->fn_field.is_const = 0;
new_sublist->fn_field.is_volatile = 0;
if (is_static)
new_sublist->fn_field.voffset = VOFFSET_STATIC;
else
new_sublist->fn_field.voffset = 0;
new_sublist->fn_field.fcontext = 0;
new_sublist->next = sublist;
sublist = new_sublist;
length++;
new_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
obstack_alloc (&objfile->type_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;
STABS_CONTINUE (pp, objfile);
}
if (nfn_fields)
{
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;
}
if (**pp == ';')
(*pp)++;
else
return 0;
return 1;
}
int
resolve_cfront_continuation (struct objfile *objfile, struct symbol *sym,
char *p)
{
struct symbol *ref_sym = 0;
char *sname;
struct field_info fi;
struct type *type;
struct cleanup *back_to;
fi.list = NULL;
fi.fnlist = NULL;
back_to = make_cleanup (null_cleanup, 0);
if (*p != 's'
&& *p != 'c'
&& *p != 'u')
return 0;
p++;
sname = get_substring (&p, ';');
if (!sname || strcmp (sname, SYMBOL_NAME (sym)))
error ("Internal error: base symbol type name does not match\n");
ref_sym = lookup_symbol (SYMBOL_NAME (sym), 0, STRUCT_NAMESPACE, 0, 0);
type = SYMBOL_TYPE (ref_sym);
if (!read_cfront_baseclasses (&fi, &p, type, objfile)
|| !copy_cfront_struct_fields (&fi, type, objfile)
|| !read_cfront_member_functions (&fi, &p, type, objfile)
|| !read_cfront_static_fields (&fi, &p, type, objfile)
|| !attach_fields_to_type (&fi, type, objfile)
|| !attach_fn_fields_to_type (&fi, type)
)
{
type = error_type (&p, objfile);
}
do_cleanups (back_to);
return 0;
}
static int
resolve_symbol_reference (struct objfile *objfile, struct symbol *sym, char *p)
{
int refnum;
struct symbol *ref_sym = 0;
struct alias_list *alias;
if (*p != '#')
return 0;
refnum = process_reference (&p);
ref_sym = ref_search (refnum);
if (!ref_sym)
{
complain (&lrs_general_complaint, "symbol for reference not found");
return 0;
}
alias = (struct alias_list *) obstack_alloc (&objfile->type_obstack,
sizeof (struct alias_list));
if (!alias)
{
complain (&lrs_general_complaint, "Unable to allocate alias list memory");
return 0;
}
alias->next = 0;
alias->sym = sym;
if (!SYMBOL_ALIASES (ref_sym))
{
SYMBOL_ALIASES (ref_sym) = alias;
}
else
{
struct alias_list *temp;
for (temp = SYMBOL_ALIASES (ref_sym);
temp->next;
temp = temp->next)
;
temp->next = alias;
}
SYMBOL_NAME (sym) = SYMBOL_NAME (ref_sym);
return 1;
}
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 CORE_ADDR
ref_search_value (int refnum)
{
if (refnum < 0 || refnum > ref_count)
return 0;
return ref_map[refnum].value;
}
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;
}
}
struct symbol *
define_symbol (CORE_ADDR valu, char *string, char *prefix,
int desc, int type, struct objfile *objfile)
{
register struct symbol *sym;
char *p = (char *) stabsread_objc_colon (string);
int deftype;
int synonym = 0;
register 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->symbol_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':
SYMBOL_NAME (sym) = obsavestring ("this", strlen ("this"),
&objfile->symbol_obstack);
break;
case 'v':
goto normal;
case 'e':
SYMBOL_NAME (sym) = obsavestring ("eh_throw", strlen ("eh_throw"),
&objfile->symbol_obstack);
break;
case '_':
goto normal;
#ifdef STATIC_TRANSFORM_NAME
case 'X':
goto normal;
#endif
default:
complain (&unrecognized_cplus_name_complaint, string);
goto normal;
}
}
else if (string[0] == '#')
{
char *s;
int refnum, nlen;
s = string;
refnum = symbol_reference_defined (&s);
if (refnum >= 0)
ref_add (refnum, sym, string, SYMBOL_VALUE (sym));
else if (!resolve_symbol_reference (objfile, sym, string))
return NULL;
nlen = p - s;
if (refnum >= 0)
{
if (nlen > 0)
{
unsigned int prefixlen = strlen (prefix);
SYMBOL_NAME (sym) = (char *)
obstack_alloc (&objfile->symbol_obstack, nlen + prefixlen + 1);
memcpy (SYMBOL_NAME (sym), prefix, prefixlen);
memcpy (SYMBOL_NAME (sym) + prefixlen, s, nlen);
SYMBOL_NAME (sym)[nlen + prefixlen] = '\0';
SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
}
else
{
unsigned int prefixlen = strlen (prefix);
nlen = p - string;
SYMBOL_NAME (sym) = (char *)
obstack_alloc (&objfile->symbol_obstack, nlen + prefixlen + 1);
memcpy (SYMBOL_NAME (sym), string, nlen);
SYMBOL_NAME (sym)[nlen] = '\0';
SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
}
}
string = s;
}
else
{
unsigned int prefixlen, nlen;
normal:
prefixlen = strlen (prefix);
nlen = p - string;
SYMBOL_LANGUAGE (sym) = current_subfile->language;
SYMBOL_NAME (sym) = (char *)
obstack_alloc (&objfile->symbol_obstack, nlen + prefixlen + 1);
memcpy (SYMBOL_NAME (sym), prefix, prefixlen);
memcpy (SYMBOL_NAME (sym) + prefixlen, string, nlen);
SYMBOL_NAME (sym)[nlen + prefixlen] = '\0';
SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
}
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_NAMESPACE (sym) = VAR_NAMESPACE;
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->symbol_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 '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_NAMESPACE (sym) = VAR_NAMESPACE;
add_symbol_to_list (sym, &file_symbols);
return sym;
case 'C':
SYMBOL_TYPE (sym) = read_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_LABEL;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
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_NAMESPACE (sym) = VAR_NAMESPACE;
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));
if (SYMBOL_LANGUAGE (sym) == language_cplus)
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_NAMESPACE (sym) = VAR_NAMESPACE;
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_NAMESPACE (sym) = VAR_NAMESPACE;
if (SYMBOL_NAME (sym) && SYMBOL_NAME (sym)[0] != '#')
{
i = hashname (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_NAMESPACE (sym) = VAR_NAMESPACE;
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);
#ifndef DBX_PARM_SYMBOL_CLASS
#define DBX_PARM_SYMBOL_CLASS(type) LOC_ARG
#endif
SYMBOL_CLASS (sym) = DBX_PARM_SYMBOL_CLASS (type);
SYMBOL_VALUE (sym) = valu;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
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 (BELIEVE_PCC_PROMOTION_TYPE)
{
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
&& TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
&& 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (pcc_promotion_type))
{
SYMBOL_VALUE (sym) += TYPE_LENGTH (pcc_promotion_type)
- TYPE_LENGTH (SYMBOL_TYPE (sym));
}
break;
}
else
{
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)
{
complain (®_value_complaint, SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_SOURCE_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
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)
{
complain (®_value_complaint, SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_SOURCE_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
if (within_function)
{
if (local_symbols
&& local_symbols->nsyms > 0
#ifndef USE_REGISTER_NOT_ARG
&& REG_STRUCT_HAS_ADDR_P ()
&& REG_STRUCT_HAS_ADDR (processing_gcc_compilation,
SYMBOL_TYPE (sym))
&& (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_SET
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_BITSTRING)
#endif
)
{
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)
&& STREQ (SYMBOL_NAME (prev_sym), SYMBOL_NAME (sym)))
{
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 (SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
if (msym != NULL)
{
SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
}
}
#endif
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
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_NAMESPACE (sym) = VAR_NAMESPACE;
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 (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)) = SYMBOL_NAME (sym);
}
}
else
TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_NAME (sym);
}
add_symbol_to_list (sym, &file_symbols);
break;
case 'T':
synonym = *p == 't';
if (synonym)
p++;
else if ((current_subfile->language == language_cplus)
|| (current_subfile->language == language_objc)
|| (current_subfile->language == language_objcplus))
synonym = 1;
SYMBOL_TYPE (sym) = read_type (&p, objfile);
if (nameless)
return NULL;
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_VALUE (sym) = valu;
SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_TAG_NAME (SYMBOL_TYPE (sym))
= obconcat (&objfile->type_obstack, "", "", SYMBOL_NAME (sym));
add_symbol_to_list (sym, &file_symbols);
if (synonym)
{
register struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
*typedef_sym = *sym;
SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
SYMBOL_VALUE (typedef_sym) = valu;
SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_NAME (SYMBOL_TYPE (sym))
= obconcat (&objfile->type_obstack, "", "", 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 (SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
if (msym != NULL)
{
SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
}
}
#endif
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
if (os9k_stabs)
add_symbol_to_list (sym, &global_symbols);
else
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_NAMESPACE (sym) = VAR_NAMESPACE;
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)
{
complain (®_value_complaint, SYMBOL_VALUE (sym),
NUM_REGS + NUM_PSEUDO_REGS,
SYMBOL_SOURCE_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM;
}
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
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_NAMESPACE (sym) = VAR_NAMESPACE;
add_symbol_to_list (sym, &local_symbols);
break;
case 'Z':
process_later (sym, p, resolve_cfront_continuation);
SYMBOL_TYPE (sym) = error_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_VALUE (sym) = 0;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
return sym;
default:
SYMBOL_TYPE (sym) = error_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_VALUE (sym) = 0;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
add_symbol_to_list (sym, &file_symbols);
break;
}
if (REG_STRUCT_HAS_ADDR_P ()
&& REG_STRUCT_HAS_ADDR (processing_gcc_compilation, SYMBOL_TYPE (sym))
&& (SYMBOL_CLASS (sym) == LOC_REGPARM || SYMBOL_CLASS (sym) == LOC_ARG))
{
struct type *symbol_type = check_typedef (SYMBOL_TYPE (sym));
if ((TYPE_CODE (symbol_type) == TYPE_CODE_STRUCT)
|| (TYPE_CODE (symbol_type) == TYPE_CODE_UNION)
|| (TYPE_CODE (symbol_type) == TYPE_CODE_BITSTRING)
|| (TYPE_CODE (symbol_type) == TYPE_CODE_SET))
{
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;
}
}
while (*p && *p == ';')
{
p++;
if (*p && p[0] == 'l' && p[1] == '(')
{
if (!resolve_live_range (objfile, sym, p))
return NULL;
p = strchr (p, ')');
if (!*p || *p != ')')
{
complain (&lrs_general_complaint, "live range format not recognized");
return NULL;
}
p++;
}
}
return sym;
}
static int
resolve_live_range (struct objfile *objfile, struct symbol *sym, char *p)
{
int refnum;
CORE_ADDR start, end;
if (!*p || *p != 'l')
{
complain (&lrs_general_complaint, "live range string 1");
return 0;
}
p++;
if (!*p || *p != '(')
{
complain (&lrs_general_complaint, "live range string 2");
return 0;
}
p++;
refnum = process_reference (&p);
start = ref_search_value (refnum);
if (!start)
{
complain (&lrs_general_complaint, "Live range symbol not found 1");
return 0;
}
if (!*p || *p != ',')
{
complain (&lrs_general_complaint, "live range string 3");
return 0;
}
p++;
refnum = process_reference (&p);
end = ref_search_value (refnum);
if (!end)
{
complain (&lrs_general_complaint, "Live range symbol not found 2");
return 0;
}
if (!*p || *p != ')')
{
complain (&lrs_general_complaint, "live range string 4");
return 0;
}
add_live_range (objfile, sym, start, end);
return 1;
}
static void
add_live_range (struct objfile *objfile, struct symbol *sym, CORE_ADDR start,
CORE_ADDR end)
{
struct range_list *r, *rs;
if (start >= end)
{
complain (&lrs_general_complaint, "end of live range follows start");
return;
}
r = (struct range_list *)
obstack_alloc (&objfile->type_obstack,
sizeof (struct range_list));
r->start = start;
r->end = end;
r->next = 0;
if (!SYMBOL_RANGES (sym))
SYMBOL_RANGES (sym) = r;
else
{
for (rs = SYMBOL_RANGES (sym); rs->next; rs = rs->next)
;
rs->next = r;
}
}
static struct type *
error_type (char **pp, struct objfile *objfile)
{
complain (&error_type_complaint);
while (1)
{
while (**pp != '\0')
{
(*pp)++;
}
if ((*pp)[-1] == '\\' || (*pp)[-1] == '?')
{
*pp = next_symbol_text (objfile);
}
else
{
break;
}
}
return (builtin_type_error);
}
struct type *
read_type (register char **pp, struct objfile *objfile)
{
register struct type *type = 0;
struct type *type1;
int typenums[2];
char type_descriptor;
int type_size = -1;
int is_string = 0;
if ((**pp >= '0' && **pp <= '9')
|| **pp == '('
|| **pp == '-')
{
if (read_type_number (pp, typenums) != 0)
return error_type (pp, objfile);
if (**pp != '=')
return dbx_alloc_type (typenums, objfile);
(*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:
{
static struct complaint msg =
{"Unrecognized cross-reference type `%c'", 0, 0};
complain (&msg, (*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->type_obstack, p - *pp + 1);
from = *pp + 1;
while (from < p)
*to++ = *from++;
*to = '\0';
*pp = from + 1;
}
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_NAMESPACE (sym) == STRUCT_NAMESPACE
&& (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
&& STREQ (SYMBOL_NAME (sym), type_name))
{
obstack_free (&objfile->type_obstack, type_name);
type = SYMBOL_TYPE (sym);
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)
{
*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));
break;
case '&':
type1 = read_type (pp, objfile);
type = make_reference_type (type1, dbx_lookup_type (typenums));
break;
case 'f':
if (os9k_stabs && **pp == '(')
{
struct type *t;
++*pp;
while (**pp != ')')
{
t = read_type (pp, objfile);
if (**pp == ',')
++ * pp;
}
}
type1 = read_type (pp, objfile);
type = make_function_type (type1, dbx_lookup_type (typenums));
break;
case 'k':
case 'c':
if (type_descriptor == 'c' && !os9k_stabs)
return error_type (pp, objfile);
type = read_type (pp, objfile);
type = make_cv_type (1, TYPE_VOLATILE (type), type,
dbx_lookup_type (typenums));
break;
case 'B':
case 'i':
if (type_descriptor == 'i' && !os9k_stabs)
return error_type (pp, objfile);
type = read_type (pp, objfile);
type = make_cv_type (TYPE_CONST (type), 1, type,
dbx_lookup_type (typenums));
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 'S':
is_string = 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)++ != ';')
complain (&invalid_member_complaint, symnum);
type = allocate_stub_method (return_type);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
}
else
{
struct type *domain = read_type (pp, objfile);
struct type *return_type;
struct type **args;
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);
type = dbx_alloc_type (typenums, objfile);
smash_to_method_type (type, domain, return_type, args);
}
break;
case 'r':
type = read_range_type (pp, typenums, objfile);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
break;
case 'b':
if (os9k_stabs)
type = read_type (pp, objfile);
else
{
type = read_sun_builtin_type (pp, typenums, objfile);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
}
break;
case 'R':
type = read_sun_floating_type (pp, typenums, objfile);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
break;
case 'e':
type = dbx_alloc_type (typenums, objfile);
type = read_enum_type (pp, type, objfile);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
break;
case 's':
case 'u':
type = dbx_alloc_type (typenums, objfile);
switch (type_descriptor)
{
case 's':
TYPE_CODE (type) = TYPE_CODE_STRUCT;
break;
case 'u':
TYPE_CODE (type) = TYPE_CODE_UNION;
break;
}
type = read_struct_type (pp, type, 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;
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)
*dbx_lookup_type (typenums) = type;
break;
default:
--*pp;
return error_type (pp, objfile);
}
if (type == 0)
{
warning ("GDB internal error, type is NULL in stabsread.c\n");
return error_type (pp, objfile);
}
if (type_size != -1)
TYPE_LENGTH (type) = (type_size + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
return type;
}
static struct type *
rs6000_builtin_type (int typenum)
{
#define NUMBER_RECOGNIZED 34
static struct type *negative_types[NUMBER_RECOGNIZED + 1];
struct type *rettype = NULL;
if (typenum >= 0 || typenum < -NUMBER_RECOGNIZED)
{
complain (&rs6000_builtin_complaint, 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", NULL);
break;
case 2:
rettype = init_type (TYPE_CODE_INT, 1, 0, "char", NULL);
break;
case 3:
rettype = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
break;
case 4:
rettype = init_type (TYPE_CODE_INT, 4, 0, "long", NULL);
break;
case 5:
rettype = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED,
"unsigned char", NULL);
break;
case 6:
rettype = init_type (TYPE_CODE_INT, 1, 0, "signed char", NULL);
break;
case 7:
rettype = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED,
"unsigned short", NULL);
break;
case 8:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned int", NULL);
break;
case 9:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned", NULL);
case 10:
rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
"unsigned long", NULL);
break;
case 11:
rettype = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
break;
case 12:
rettype = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
break;
case 13:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
break;
case 14:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "long double", NULL);
break;
case 15:
rettype = init_type (TYPE_CODE_INT, 4, 0, "integer", NULL);
break;
case 16:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"boolean", NULL);
break;
case 17:
rettype = init_type (TYPE_CODE_FLT, 4, 0, "short real", NULL);
break;
case 18:
rettype = init_type (TYPE_CODE_FLT, 8, 0, "real", NULL);
break;
case 19:
rettype = init_type (TYPE_CODE_ERROR, 0, 0, "stringptr", NULL);
break;
case 20:
rettype = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED,
"character", NULL);
break;
case 21:
rettype = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED,
"logical*1", NULL);
break;
case 22:
rettype = init_type (TYPE_CODE_BOOL, 2, TYPE_FLAG_UNSIGNED,
"logical*2", NULL);
break;
case 23:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"logical*4", NULL);
break;
case 24:
rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
"logical", NULL);
break;
case 25:
rettype = init_type (TYPE_CODE_COMPLEX, 8, 0, "complex", NULL);
break;
case 26:
rettype = init_type (TYPE_CODE_COMPLEX, 16, 0, "double complex", NULL);
break;
case 27:
rettype = init_type (TYPE_CODE_INT, 1, 0, "integer*1", NULL);
break;
case 28:
rettype = init_type (TYPE_CODE_INT, 2, 0, "integer*2", NULL);
break;
case 29:
rettype = init_type (TYPE_CODE_INT, 4, 0, "integer*4", NULL);
break;
case 30:
rettype = init_type (TYPE_CODE_CHAR, 2, 0, "wchar", NULL);
break;
case 31:
rettype = init_type (TYPE_CODE_INT, 8, 0, "long long", NULL);
break;
case 32:
rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
"unsigned long long", NULL);
break;
case 33:
rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
"logical*8", NULL);
break;
case 34:
rettype = init_type (TYPE_CODE_INT, 8, 0, "integer*8", NULL);
break;
}
negative_types[-typenum] = rettype;
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 skip_method;
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;
register char *p;
while (**pp != ';')
{
p = *pp;
while (*p != ':')
{
p++;
}
if (p[1] != ':')
{
break;
}
sublist = NULL;
look_ahead_type = NULL;
length = 0;
skip_method = 0;
if (p - *pp == strlen ("__base_ctor")
&& strncmp (*pp, "__base_ctor", strlen ("__base_ctor")) == 0)
skip_method = 1;
else if (p - *pp == strlen ("__base_dtor")
&& strncmp (*pp, "__base_dtor", strlen ("__base_dtor")) == 0)
skip_method = 1;
else if (p - *pp == strlen ("__deleting_dtor")
&& strncmp (*pp, "__deleting_dtor",
strlen ("__deleting_dtor")) == 0)
skip_method = 1;
if (skip_method)
{
*pp = p + 2;
read_type (pp, objfile);
while (**pp != ';')
(*pp) ++;
(*pp) ++;
while (**pp != ';')
(*pp) ++;
(*pp) ++;
continue;
}
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] =
{'o', 'p', CPLUS_MARKER};
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 = main_fn_name;
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 = savestring (*pp, p - *pp);
*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:
complain (&const_vol_complaint, **pp);
break;
}
switch (*(*pp)++)
{
case '*':
{
int nbits;
new_sublist->fn_field.voffset =
(0x7fffffff & read_huge_number (pp, ';', &nbits)) + 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 '?':
new_sublist->fn_field.voffset = VOFFSET_STATIC;
if (strncmp (new_sublist->fn_field.physname,
main_fn_name, strlen (main_fn_name)))
{
new_sublist->fn_field.is_stub = 1;
}
break;
default:
complain (&member_fn_complaint, (*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)++;
new_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
obstack_alloc (&objfile->type_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;
STABS_CONTINUE (pp, objfile);
}
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)
{
register 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->type_obstack, vptr_name, name, "");
break;
case 'b':
name = type_name_no_tag (context);
if (name == NULL)
{
complain (&invalid_cpp_type_complaint, symnum);
name = "FOO";
}
fip->list->field.name =
obconcat (&objfile->type_obstack, vb_name, name, "");
break;
default:
complain (&invalid_cpp_abbrev_complaint, *pp);
fip->list->field.name =
obconcat (&objfile->type_obstack,
"INVALID_CPLUSPLUS_ABBREV", "", "");
break;
}
p = ++(*pp);
if (p[-1] != ':')
{
complain (&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);
if (nbits != 0)
return 0;
}
FIELD_BITSIZE (fip->list->field) = 0;
fip->list->visibility = VISIBILITY_PRIVATE;
}
else
{
complain (&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)
{
if (ARM_DEMANGLING && current_subfile->language == language_cplus)
{
char save_p;
char *dem, *dem_p;
save_p = *p;
*p = '\0';
dem = cplus_demangle (*pp, DMGL_ANSI | DMGL_PARAMS);
if (dem != NULL)
{
dem_p = strrchr (dem, ':');
if (dem_p != 0 && *(dem_p - 1) == ':')
dem_p++;
FIELD_NAME (fip->list->field) =
obsavestring (dem_p, strlen (dem_p), &objfile->type_obstack);
}
else
{
FIELD_NAME (fip->list->field) =
obsavestring (*pp, p - *pp, &objfile->type_obstack);
}
*p = save_p;
}
else
fip->list->field.name =
obsavestring (*pp, p - *pp, &objfile->type_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, savestring (*pp, p - *pp));
*pp = p + 1;
return;
}
else if (**pp != ',')
{
complain (&stabs_general_complaint, "bad structure-type format");
return;
}
(*pp)++;
{
int nbits;
FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ',', &nbits);
if (nbits != 0)
{
complain (&stabs_general_complaint, "bad structure-type format");
return;
}
FIELD_BITSIZE (fip->list->field) = read_huge_number (pp, ';', &nbits);
if (nbits != 0)
{
complain (&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
{
struct type *field_type = check_typedef (FIELD_TYPE (fip->list->field));
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 (fip->list->field) = 0;
}
if ((FIELD_BITSIZE (fip->list->field)
== TARGET_CHAR_BIT * TYPE_LENGTH (field_type)
|| (TYPE_CODE (field_type) == TYPE_CODE_ENUM
&& FIELD_BITSIZE (fip->list->field) == TARGET_INT_BIT)
)
&&
FIELD_BITPOS (fip->list->field) % 8 == 0)
{
FIELD_BITSIZE (fip->list->field) = 0;
}
}
}
static int
read_struct_fields (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
register char *p;
struct nextfield *new;
p = *pp;
while (**pp != ';' && **pp != '\0')
{
if (os9k_stabs && **pp == ',')
break;
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);
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:
{
static struct complaint msg =
{
"Unknown virtual character `%c' for baseclass", 0, 0};
complain (&msg, **pp);
}
}
++(*pp);
new->visibility = *(*pp)++;
switch (new->visibility)
{
case VISIBILITY_PRIVATE:
case VISIBILITY_PROTECTED:
case VISIBILITY_PUBLIC:
break;
default:
{
static struct complaint msg =
{
"Unknown visibility `%c' for baseclass", 0, 0
};
complain (&msg, new->visibility);
new->visibility = VISIBILITY_PUBLIC;
}
}
{
int nbits;
FIELD_BITPOS (new->field) = read_huge_number (pp, ',', &nbits);
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)
{
register 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)
{
if (!strncmp (TYPE_FIELD_NAME (t, i), vptr_name,
sizeof (vptr_name) - 1))
{
TYPE_VPTR_FIELDNO (type) = i;
goto gotit;
}
}
complain (&vtbl_notfound_complaint, 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, register struct type *type)
{
register 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
read_cfront_static_fields (struct field_info *fip, char **pp, struct type *type,
struct objfile *objfile)
{
struct nextfield *new;
struct type *stype;
char *sname;
struct symbol *ref_static = 0;
if (**pp == ';')
{
++(*pp);
return 1;
}
STABS_CONTINUE (pp, objfile);
while (**pp != ';' && (sname = get_substring (pp, ' '), sname))
{
ref_static = lookup_symbol (sname, 0, VAR_NAMESPACE, 0, 0);
if (!ref_static)
{
static struct complaint msg =
{"\
Unable to find symbol for static data field %s\n",
0, 0};
complain (&msg, sname);
continue;
}
stype = SYMBOL_TYPE (ref_static);
new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (xfree, new);
memset (new, 0, sizeof (struct nextfield));
new->next = fip->list;
fip->list = new;
new->visibility = VISIBILITY_PUBLIC;
fip->list->field.type = stype;
SET_FIELD_PHYSNAME (fip->list->field, savestring (sname, strlen (sname)));
if (ARM_DEMANGLING)
{
char *dem, *dem_p;
dem = cplus_demangle (sname, DMGL_ANSI | DMGL_PARAMS);
if (dem != NULL)
{
dem_p = strrchr (dem, ':');
if (dem_p != 0 && *(dem_p - 1) == ':')
dem_p++;
fip->list->field.name =
obsavestring (dem_p, strlen (dem_p), &objfile->type_obstack);
}
else
{
fip->list->field.name =
obsavestring (sname, strlen (sname), &objfile->type_obstack);
}
}
}
return 1;
}
static int
copy_cfront_struct_fields (struct field_info *fip, struct type *type,
struct objfile *objfile)
{
int nfields = TYPE_NFIELDS (type);
int i;
struct nextfield *new;
for (i = 0; i < nfields; 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;
new->field = TYPE_FIELD (type, i);
if (TYPE_FIELD_PROTECTED (type, i))
new->visibility = VISIBILITY_PROTECTED;
else if (TYPE_FIELD_PRIVATE (type, i))
new->visibility = VISIBILITY_PRIVATE;
else
new->visibility = VISIBILITY_PUBLIC;
}
TYPE_FIELDS (type) = 0;
TYPE_NFIELDS (type) = 0;
return 1;
}
static int
attach_fields_to_type (struct field_info *fip, register struct type *type,
struct objfile *objfile)
{
register int nfields = 0;
register int non_public_fields = 0;
register 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:
{
static struct complaint msg =
{
"Unknown visibility `%c' for field", 0, 0};
complain (&msg, fip->list->visibility);
}
break;
}
fip->list = fip->list->next;
}
return 1;
}
static struct type *
read_struct_type (char **pp, struct type *type, struct objfile *objfile)
{
struct cleanup *back_to;
struct field_info fi;
fi.list = NULL;
fi.fnlist = NULL;
back_to = make_cleanup (null_cleanup, 0);
INIT_CPLUS_SPECIFIC (type);
TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
{
int nbits;
TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits);
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);
}
finish_cv_type (type);
do_cleanups (back_to);
return (type);
}
static struct type *
read_array_type (register char **pp, register struct type *type,
struct objfile *objfile)
{
struct type *index_type, *element_type, *range_type;
int lower, upper;
int adjustable = 0;
int nbits;
if (os9k_stabs)
index_type = builtin_type_int;
else
{
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, os9k_stabs ? ',' : ';', &nbits);
if (nbits != 0)
return error_type (pp, objfile);
if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
{
(*pp)++;
adjustable = 1;
}
upper = read_huge_number (pp, ';', &nbits);
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 (register char **pp, register struct type *type,
struct objfile *objfile)
{
register char *p;
char *name;
register long n;
register struct symbol *sym;
int nsyms = 0;
struct pending **symlist;
struct pending *osyms, *syms;
int o_nsyms;
int nbits;
unsigned long data;
int sign;
int signed_required = 0;
int unsigned_required = 0;
#if 0
if (within_function)
symlist = &local_symbols;
else
#endif
symlist = &file_symbols;
osyms = *symlist;
o_nsyms = osyms ? osyms->nsyms : 0;
if (os9k_stabs)
{
read_huge_number (pp, 0, &nbits);
if (nbits != 0)
return error_type (pp, objfile);
}
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->symbol_obstack);
*pp = p + 1;
read_huge_number_raw (pp, ',', &nbits, &sign, &data);
if (nbits != 0)
return error_type (pp, objfile);
if (((sign > 0) && (data > UENUM_MAX))
|| ((sign < 0) && (data > MINUS_ENUM_MIN)))
return error_type (pp, objfile);
if (sign < 0)
signed_required = 1;
if ((sign > 0) && (data > ENUM_MAX))
unsigned_required = 1;
if (signed_required && unsigned_required)
return error_type (pp, objfile);
sym = (struct symbol *)
obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_NAME (sym) = name;
SYMBOL_LANGUAGE (sym) = current_subfile->language;
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
if (sign > 0)
{
SYMBOL_VALUE (sym) = data;
}
else
{
SYMBOL_VALUE (sym) = -data;
}
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 (!signed_required)
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) = 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);
if (nbits != 0)
return error_type (pp, objfile);
read_huge_number (pp, ';', &nbits);
if (nbits != 0)
return error_type (pp, objfile);
type_bits = read_huge_number (pp, 0, &nbits);
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;
details = read_huge_number (pp, ';', &nbits);
if (nbits != 0)
return error_type (pp, objfile);
nbytes = read_huge_number (pp, ';', &nbits);
if (nbits != 0)
return error_type (pp, objfile);
if (details == NF_COMPLEX || details == NF_COMPLEX16
|| details == NF_COMPLEX32)
return init_type (TYPE_CODE_COMPLEX, nbytes, 0, NULL, objfile);
return init_type (TYPE_CODE_FLT, nbytes, 0, NULL, objfile);
}
static void
read_huge_number_raw (char **pp, int end,
int *bits, int *sign, unsigned long *data)
{
char *p = *pp;
long n = 0;
int radix = 10;
char overflow = 0;
int nbits = 0;
int c;
*data = 0;
*sign = 1;
if (*p == '-')
{
*sign = -1;
p++;
}
if (*p == '0')
{
radix = 8;
p++;
}
while ((c = *p++) >= '0' && c < ('0' + radix))
{
if (n > (ULONG_MAX / radix))
overflow = 1;
n *= radix;
if (n > (ULONG_MAX - (c - '0')))
overflow = 1;
n += c - '0';
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;
}
}
else
--p;
*pp = p;
if (overflow)
{
if (nbits == 0)
{
if (bits != NULL)
*bits = -1;
return;
}
if (bits)
*bits = nbits;
}
else
{
if (bits)
*bits = 0;
*data = n;
}
return;
}
static long
read_huge_number (char **pp, int end, int *bits)
{
int sign;
unsigned long data;
read_huge_number_raw (pp, end, bits, &sign, &data);
if (*bits > 0)
{
if (sign < 0)
*bits += 1;
}
if (*bits < 0)
{
return 0;
}
if (os9k_stabs)
{
return sign * data;
}
if ((sign > 0) && (data > (unsigned long) LONG_MAX))
{
*bits = 32;
return 0;
}
if ((sign < 0) && (data > (unsigned long) MINUS_LONG_MIN))
{
*bits = 32;
return 0;
}
return sign * data;
}
static struct type *
read_range_type (char **pp, int typenums[2], 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);
n3 = read_huge_number (pp, ';', &n3bits);
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 == 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, 0, NULL, objfile);
else if (current_symbol && SYMBOL_LANGUAGE (current_symbol) == language_chill
&& !self_subrange)
goto handle_true_range;
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);
if (index_type == NULL)
{
static struct type *range_type_index;
complain (&range_type_base_complaint, 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 type **
read_args (char **pp, int end, struct objfile *objfile)
{
struct type *types[1024], **rval;
int n = 0;
while (**pp != end)
{
if (**pp != ',')
return (struct type **) -1;
(*pp)++;
STABS_CONTINUE (pp, objfile);
types[n++] = read_type (pp, objfile);
}
(*pp)++;
if (n == 0)
{
return (struct type **) -1;
}
if (n == 1)
{
rval = (struct type **) xmalloc (2 * sizeof (struct type *));
}
else if (TYPE_CODE (types[n - 1]) != TYPE_CODE_VOID)
{
rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
memset (rval + n, 0, sizeof (struct type *));
}
else
{
rval = (struct type **) xmalloc (n * sizeof (struct type *));
}
memcpy (rval, types, n * sizeof (struct type *));
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)
{
static struct complaint msg =
{
"Invalid symbol data: common block within common block",
0, 0};
complain (&msg);
}
common_block = local_symbols;
common_block_i = local_symbols ? local_symbols->nsyms : 0;
common_block_name = obsavestring (name, strlen (name),
&objfile->symbol_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)
{
static struct complaint msg =
{"ECOMM symbol unmatched by BCOMM", 0, 0};
complain (&msg);
return;
}
sym = (struct symbol *)
obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
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 (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)
{
register int j;
for (j = next->nsyms - 1; j >= 0; j--)
SYMBOL_VALUE_ADDRESS (next->symbol[j]) += valu;
}
}
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)
{
static struct complaint msg =
{"need a type name", 0, 0};
complain (&msg);
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_NAMESPACE (sym) == STRUCT_NAMESPACE
&& (TYPE_CODE (SYMBOL_TYPE (sym)) ==
TYPE_CODE (*type))
&& STREQ (SYMBOL_NAME (sym), typename))
{
memcpy (*type, SYMBOL_TYPE (sym),
sizeof (struct type));
}
}
}
}
}
break;
default:
{
static struct complaint msg =
{"\
GDB internal error. cleanup_undefined_types with bad type %d.", 0, 0};
complain (&msg, TYPE_CODE (*type));
}
break;
}
}
undef_types_length = 0;
}
void
scan_file_globals (struct objfile *objfile)
{
int hash;
struct minimal_symbol *msymbol;
struct symbol *sym, *prev, *rsym;
struct objfile *resolve_objfile;
if (symfile_objfile && objfile != symfile_objfile)
resolve_objfile = symfile_objfile;
else
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 && 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 (SYMBOL_NAME (msymbol));
for (sym = global_sym_chain[hash]; sym;)
{
if (SYMBOL_NAME (msymbol)[0] == SYMBOL_NAME (sym)[0] &&
STREQ (SYMBOL_NAME (msymbol) + 1, SYMBOL_NAME (sym) + 1))
{
struct alias_list *aliases;
if (prev)
{
SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
}
else
{
global_sym_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
}
rsym = sym;
aliases = SYMBOL_ALIASES (sym);
while (rsym)
{
if (SYMBOL_CLASS (rsym) == LOC_BLOCK)
{
fix_common_block (rsym,
SYMBOL_VALUE_ADDRESS (msymbol));
}
else
{
SYMBOL_VALUE_ADDRESS (rsym)
= SYMBOL_VALUE_ADDRESS (msymbol);
}
SYMBOL_SECTION (rsym) = SYMBOL_SECTION (msymbol);
if (aliases)
{
rsym = aliases->sym;
aliases = aliases->next;
}
else
rsym = NULL;
}
if (prev)
{
sym = SYMBOL_VALUE_CHAIN (prev);
}
else
{
sym = global_sym_chain[hash];
}
}
else
{
prev = sym;
sym = SYMBOL_VALUE_CHAIN (sym);
}
}
}
if (resolve_objfile == objfile)
break;
resolve_objfile = objfile;
}
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
complain (&unresolved_sym_chain_complaint,
objfile->name, 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;
os9k_stabs = 0;
}
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 *
stabsread_objc_colon (name)
char *name;
{
char *s = name;
if (s[0] == '-' || *s == '+')
{
if (s[1] != '[')
{
error ("invalid symbol name \"%s\"", name);
}
s = strchr (s, ']');
if (s == NULL)
{
error ("invalid symbol name \"%s\"", name);
}
return strchr (s, ':');
}
else
{
return strchr (s, ':');
}
}
void
_initialize_stabsread (void)
{
undef_types_allocated = 20;
undef_types_length = 0;
undef_types = (struct type **)
xmalloc (undef_types_allocated * sizeof (struct type *));
}