#include "defs.h"
#include "symtab.h"
#include "frame.h"
#include "command.h"
#include "symfile.h"
#include "objfiles.h"
#include "source.h"
#include "demangle.h"
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
#include "parser-defs.h"
#include "block.h"
#include "objc-lang.h"
#include "linespec.h"
#include "language.h"
#include "ui-out.h"
#include "exceptions.h"
#include "gdb_assert.h"
int allow_objc_selectors_flag = 1;
extern char *operator_chars (char *, char **);
static void initialize_defaults (struct symtab **default_symtab,
int *default_line);
static void set_flags (char *arg, int *is_quoted, char **paren_pointer);
static struct symtabs_and_lines decode_indirect (char **argptr);
static char *locate_first_half (char **argptr, int *is_quote_enclosed);
static struct symtabs_and_lines decode_objc (char **argptr,
int funfirstline,
struct symtab *file_symtab,
char ***canonical,
char *saved_arg);
static struct symtabs_and_lines decode_compound (char **argptr,
int funfirstline,
char ***canonical,
char *saved_arg,
char *p,
int *not_found_ptr);
static struct symbol *lookup_prefix_sym (char **argptr, char *p);
static struct symtabs_and_lines find_method (int funfirstline,
char ***canonical,
char *saved_arg,
char *copy,
struct type *t,
struct symbol *sym_class,
int *not_found_ptr);
static int collect_methods (char *copy, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size);
static NORETURN void cplusplus_error (const char *name,
const char *fmt, ...)
ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
static int total_number_of_methods (struct type *type);
static int find_methods (struct type *, char *, struct symbol ***, int *,
int *);
static int add_matching_methods (int method_counter, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size,
int *sym_arr_pos);
static int add_constructors (int method_counter, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size,
int *sym_arr_pos);
static void build_canonical_line_spec (struct symtab_and_line *,
char *, char ***);
static char *find_toplevel_char (char *s, char c);
static int is_objc_method_format (const char *s);
static struct symtabs_and_lines decode_line_2 (struct symbol *[],
int, int, int, int, char ***);
static struct symtab **symtab_from_filename (char **argptr,
char *p, int is_quote_enclosed,
int *not_found_ptr);
static struct
symtabs_and_lines decode_all_digits_exhaustive (char **argptr,
int funfirstline,
struct symtab *default_symtab,
int default_line,
char ***canonical,
struct symtab *file_symtab,
char *q,
int *parsed_lineno);
static struct
symtabs_and_lines decode_all_digits (char **argptr,
int funfirstline,
struct symtab *default_symtab,
int default_line,
char ***canonical,
struct symtab *file_symtab,
char *q);
static struct symtabs_and_lines decode_dollar (char *copy,
int funfirstline,
struct symtab *default_symtab,
char ***canonical,
struct symtab *file_symtab);
static struct symtabs_and_lines decode_variable (char *copy,
int funfirstline,
int equivalencies,
char ***canonical,
struct symtab *file_symtab,
int *not_found_ptr);
static struct symtabs_and_lines decode_all_variables (char *copy,
int funfirstline,
int equivalencies,
char ***canonical,
struct symtab *file_symtab,
int *not_found_ptr);
static struct
symtabs_and_lines symbol_found (int funfirstline,
char ***canonical,
char *copy,
struct symbol *sym,
struct symtab *file_symtab,
struct symtab *sym_symtab);
static struct
symtabs_and_lines symbols_found (int funfirstline,
char ***canonical,
char *copy,
struct symbol_search *sym_list,
struct symtab *file_symtab);
static struct
symtabs_and_lines minsym_found (int funfirstline, int equivalencies,
struct minimal_symbol *msymbol,
char ***canonical);
static struct
symtabs_and_lines minsyms_found (int funfirstline, int equivalencies,
struct symbol_search *sym_list,
char ***canonical);
static NORETURN void
cplusplus_error (const char *name, const char *fmt, ...)
{
struct ui_file *tmp_stream;
tmp_stream = mem_fileopen ();
make_cleanup_ui_file_delete (tmp_stream);
{
va_list args;
va_start (args, fmt);
vfprintf_unfiltered (tmp_stream, fmt, args);
va_end (args);
}
while (*name == '\'')
name++;
fprintf_unfiltered (tmp_stream,
("Hint: try '%s<TAB> or '%s<ESC-?>\n"
"(Note leading single quote.)"),
name, name);
error_stream (tmp_stream);
}
static int
total_number_of_methods (struct type *type)
{
int n;
int count;
CHECK_TYPEDEF (type);
if (TYPE_CPLUS_SPECIFIC (type) == NULL)
return 0;
count = TYPE_NFN_FIELDS_TOTAL (type);
for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
count += total_number_of_methods (TYPE_BASECLASS (type, n));
return count;
}
static int
find_methods (struct type *t, char *name, struct symbol ***sym_arr,
int *sym_arr_size, int *sym_arr_pos)
{
int i1 = 0;
int ibase;
char *class_name = type_name_no_tag (t);
struct cleanup *old_chain;
old_chain = make_cleanup_restore_language (language_cplus);
if (class_name
&& (lookup_symbol (class_name, (struct block *) NULL,
STRUCT_DOMAIN, (int *) NULL,
(struct symtab **) NULL)))
{
int method_counter;
int name_len = strlen (name);
CHECK_TYPEDEF (t);
for (method_counter = TYPE_NFN_FIELDS (t) - 1;
method_counter >= 0;
--method_counter)
{
char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
char dem_opname[64];
if (strncmp (method_name, "__", 2) == 0 ||
strncmp (method_name, "op", 2) == 0 ||
strncmp (method_name, "type", 4) == 0)
{
if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
method_name = dem_opname;
else if (cplus_demangle_opname (method_name, dem_opname, 0))
method_name = dem_opname;
}
if (strcmp_iw (name, method_name) == 0)
i1 += add_matching_methods (method_counter, t,
sym_arr, sym_arr_size,
sym_arr_pos);
else if (strncmp (class_name, name, name_len) == 0
&& (class_name[name_len] == '\0'
|| class_name[name_len] == '<'))
i1 += add_constructors (method_counter, t,
sym_arr, sym_arr_size,
sym_arr_pos);
}
}
if (i1 == 0)
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr,
sym_arr_size, sym_arr_pos);
do_cleanups (old_chain);
return i1;
}
static void
remove_duplicate_symbols (struct symbol **sym_arr, int sym_arr_pos,
struct symbol_search **sym_list)
{
struct symbol_search *cur;
struct symbol_search *prev;
int i;
for (i = 0; i < sym_arr_pos; i++)
{
prev = NULL;
cur = *sym_list;
while (cur)
{
if (cur->symbol == sym_arr[i])
{
if (prev)
prev->next = cur->next;
else
*sym_list = cur->next;
}
else
prev = cur;
cur = cur->next;
}
}
}
static int
add_matching_methods (int method_counter, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size,
int *sym_arr_pos)
{
int field_counter;
int i1 = 0;
int syms_found;
struct symbol_search *sym_list;
for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
field_counter >= 0;
--field_counter)
{
struct fn_field *f;
char *phys_name;
syms_found = 0;
sym_list = NULL;
f = TYPE_FN_FIELDLIST1 (t, method_counter);
if (TYPE_FN_FIELD_STUB (f, field_counter))
{
char *tmp_name;
tmp_name = gdb_mangle_name (t,
method_counter,
field_counter);
phys_name = alloca (strlen (tmp_name) + 1);
strcpy (phys_name, tmp_name);
xfree (tmp_name);
}
else
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
if (is_destructor_name (phys_name) != 0)
continue;
if (phys_name[0] != '_')
{
char *demangled_name = alloca (strlen (TYPE_NAME (t)) +
strlen (phys_name) + 3);
sprintf (demangled_name, "%s::%s", TYPE_NAME (t), phys_name);
syms_found = lookup_symbol_all (demangled_name, NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL,
&sym_list);
}
else
syms_found = lookup_symbol_all (phys_name, NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL,
&sym_list);
if (syms_found)
{
int j;
int num_syms = 0;
int base_pos = *sym_arr_pos;
int new_pos = *sym_arr_pos;
struct symbol_search *cur;
remove_duplicate_symbols (*sym_arr, *sym_arr_pos,
&sym_list);
for (cur = sym_list; cur; cur = cur->next)
num_syms++;
if ((base_pos + num_syms) > *sym_arr_size)
{
int k;
*sym_arr = xrealloc (*sym_arr,
(num_syms + base_pos) * sizeof
(struct symbol *));
for (k = *sym_arr_size; k < num_syms + base_pos; k++)
(*sym_arr)[k] = NULL;
*sym_arr_size = num_syms + base_pos;
}
for (j = 0, cur = sym_list; j < num_syms && cur;
j++, cur = cur->next)
{
(*sym_arr)[j + base_pos] = cur->symbol;
new_pos++;
}
i1 += num_syms;
*sym_arr_pos = new_pos;
}
else
{
}
}
return i1;
}
static int
add_constructors (int method_counter, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size,
int *sym_arr_pos)
{
int field_counter;
int i1 = 0;
int syms_found = 0;
struct symbol_search *sym_list = NULL;
for (field_counter
= TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
field_counter >= 0;
--field_counter)
{
struct fn_field *f;
char *phys_name;
f = TYPE_FN_FIELDLIST1 (t, method_counter);
if (TYPE_FN_FIELD_STUB (f, field_counter))
continue;
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
if (! is_constructor_name (phys_name))
continue;
syms_found = lookup_symbol_all (phys_name, NULL,
VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL,
&sym_list);
if (syms_found)
{
int j;
int num_syms = 0;
int base_pos = *sym_arr_pos;
int new_pos = *sym_arr_pos;
struct symbol_search *cur;
remove_duplicate_symbols (*sym_arr, *sym_arr_pos,
&sym_list);
for (cur = sym_list; cur; cur = cur->next)
num_syms++;
if ((num_syms + base_pos) > *sym_arr_size)
{
int k;
*sym_arr = xrealloc (*sym_arr,
(num_syms + base_pos) * sizeof
(struct symbol *));
for (k = *sym_arr_size; k < num_syms + base_pos; k++)
(*sym_arr)[k] = NULL;
*sym_arr_size = num_syms + base_pos;
}
i1 = num_syms;
for (j = 0, cur = sym_list; j < num_syms && cur;
j++, cur = cur->next)
{
(*sym_arr)[j + base_pos] = cur->symbol;
new_pos++;
}
*sym_arr_pos = new_pos;
}
}
return i1;
}
static void
build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
char ***canonical)
{
char **canonical_arr;
char *canonical_name;
char *filename;
struct symtab *s = sal->symtab;
if (s == (struct symtab *) NULL
|| s->filename == (char *) NULL
|| canonical == (char ***) NULL)
return;
canonical_arr = (char **) xmalloc (sizeof (char *));
*canonical = canonical_arr;
filename = s->filename;
if (symname != NULL)
{
canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
sprintf (canonical_name, "%s:%s", filename, symname);
}
else
{
canonical_name = xmalloc (strlen (filename) + 30);
sprintf (canonical_name, "%s:%d", filename, sal->line);
}
canonical_arr[0] = canonical_name;
}
static char *
find_toplevel_char (char *s, char c)
{
int quoted = 0;
int depth = 0;
char *scan;
for (scan = s; *scan; scan++)
{
if (quoted)
{
if (*scan == quoted)
quoted = 0;
else if (*scan == '\\' && *(scan + 1))
scan++;
}
else if (*scan == c && ! quoted && depth == 0)
return scan;
else if (*scan == '"' || *scan == '\'')
quoted = *scan;
else if (*scan == '(' || *scan == '<')
depth++;
else if ((*scan == ')' || *scan == '>') && depth > 0)
depth--;
}
return 0;
}
static int
is_objc_method_format (const char *s)
{
if (s == NULL || *s == '\0')
return 0;
if ((s[0] == ':') && (strchr ("+-", s[1]) != NULL)
&& (s[2] == '[') && strchr(s, ']'))
return 1;
else if ((strchr ("+-", s[0]) != NULL) && (s[1] == '[') && strchr(s, ']'))
return 1;
return 0;
}
static struct symtabs_and_lines
decode_line_2 (struct symbol *sym_arr[], int nelts, int nsyms, int funfirstline,
int accept_all,
char ***canonical)
{
struct symtabs_and_lines values, return_values;
char *args, *arg1;
int i;
char *prompt;
char *symname;
struct cleanup *old_chain;
char **canonical_arr = (char **) NULL;
values.sals = (struct symtab_and_line *)
alloca (nelts * sizeof (struct symtab_and_line));
return_values.sals = (struct symtab_and_line *)
xmalloc (nelts * sizeof (struct symtab_and_line));
old_chain = make_cleanup (xfree, return_values.sals);
if (canonical)
{
canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
make_cleanup (xfree, canonical_arr);
memset (canonical_arr, 0, nelts * sizeof (char *));
*canonical = canonical_arr;
}
i = 0;
if (!accept_all)
printf_unfiltered (_("[0] cancel\n[1] all\n"));
while (i < nsyms)
{
init_sal (&return_values.sals[i]);
init_sal (&values.sals[i]);
if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
{
values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
if (!accept_all)
{
if (values.sals[i].symtab)
printf_unfiltered ("[%d] %s at %s:%d\n",
(i + 2),
SYMBOL_PRINT_NAME (sym_arr[i]),
values.sals[i].symtab->filename,
values.sals[i].line);
else
printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n",
(i + 2),
SYMBOL_PRINT_NAME (sym_arr[i]),
values.sals[i].line);
}
}
else if (!accept_all)
{
printf_filtered ("[%d] %s\n",
(i + 2),
(sym_arr[i] && SYMBOL_PRINT_NAME (sym_arr[i])) ?
SYMBOL_PRINT_NAME (sym_arr[i]) : "?HERE?");
}
else
printf_unfiltered (_("?HERE\n"));
i++;
}
if (!accept_all && nelts != nsyms)
printf_filtered ("\nNon-debugging symbols:\n");
for (i = nsyms; i < nelts; i++)
{
QUIT;
values.sals[i].symtab = 0;
values.sals[i].line = 0;
values.sals[i].end = 0;
values.sals[i].pc = SYMBOL_VALUE_ADDRESS (sym_arr[i]);
values.sals[i].section = SYMBOL_BFD_SECTION (sym_arr[i]);
if (funfirstline)
{
if (SKIP_PROLOGUE_ADDR_CTX_P ())
{
struct address_context sym_addr_ctx;
init_address_context (&sym_addr_ctx);
sym_addr_ctx.address = values.sals[i].pc;
sym_addr_ctx.symbol = sym_arr[i];
sym_addr_ctx.bfd_section = SYMBOL_BFD_SECTION (sym_arr[i]);
values.sals[i].pc = SKIP_PROLOGUE_ADDR_CTX (&sym_addr_ctx);
}
else
{
values.sals[i].pc = SKIP_PROLOGUE (values.sals[i].pc);
}
}
if (!accept_all)
printf_filtered ("[%d] %s\n",
(i + 2),
SYMBOL_PRINT_NAME (sym_arr[i]));
}
if (!accept_all)
{
prompt = getenv ("PS2");
if (prompt == NULL)
{
prompt = "> ";
}
args = command_line_input (prompt, 0, "overload-choice");
if (args == 0 || *args == 0)
error_no_arg ("one or more choice numbers");
}
else
args = "1";
i = 0;
while (*args)
{
int num;
arg1 = args;
while (*arg1 >= '0' && *arg1 <= '9')
arg1++;
if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
error (_("Arguments must be choice numbers."));
num = atoi (args);
if (num == 0)
error (_("canceled"));
else if (num == 1)
{
if (canonical_arr)
{
for (i = 0; i < nelts; i++)
{
if (canonical_arr[i] == NULL)
{
symname = DEPRECATED_SYMBOL_NAME (sym_arr[i]);
canonical_arr[i] = savestring (symname, strlen (symname));
}
}
}
memcpy (return_values.sals, values.sals,
(nelts * sizeof (struct symtab_and_line)));
return_values.nelts = nelts;
discard_cleanups (old_chain);
return return_values;
}
if (num >= nelts + 2)
{
printf_unfiltered (_("No choice number %d.\n"), num);
}
else
{
num -= 2;
if (values.sals[num].pc)
{
if (canonical_arr)
{
symname = DEPRECATED_SYMBOL_NAME (sym_arr[num]);
make_cleanup (xfree, symname);
canonical_arr[i] = savestring (symname, strlen (symname));
}
return_values.sals[i++] = values.sals[num];
values.sals[num].pc = 0;
}
else
{
printf_unfiltered (_("duplicate request for %d ignored.\n"), num);
}
}
args = arg1;
while (*args == ' ' || *args == '\t')
args++;
}
return_values.nelts = i;
discard_cleanups (old_chain);
return return_values;
}
static void
sals_pushback (struct symtabs_and_lines *sals,
struct symtab_and_line *sal,
unsigned int num_sals)
{
const unsigned int total_num_sals = sals->nelts + num_sals;
sals->sals = (struct symtab_and_line *)
xrealloc (sals->sals,
total_num_sals * sizeof (struct symtab_and_line));
memcpy (sals->sals + sals->nelts, sal,
num_sals * sizeof (struct symtab_and_line));
sals->nelts += num_sals;
}
static void
intersect_sals (struct symtabs_and_lines *dst_sals,
const struct symtabs_and_lines *src_sals)
{
if (src_sals->nelts > 0)
{
int src_idx;
int dst_idx;
for (src_idx = 0; src_idx < src_sals->nelts; src_idx++)
{
int add_src = 1;
struct symtab_and_line *src_sal = &src_sals->sals[src_idx];
for (dst_idx = 0; dst_idx < dst_sals->nelts; dst_idx++)
{
struct symtab_and_line *dst_sal = &dst_sals->sals[dst_idx];
if (dst_sal->pc == src_sal->pc
&& dst_sal->line == src_sal->line
&& dst_sal->symtab
&& src_sal->symtab
&& dst_sal->symtab->objfile ==
src_sal->symtab->objfile->separate_debug_objfile)
{
add_src = 0;
break;
}
}
if (add_src)
{
sals_pushback (dst_sals, src_sal, 1);
}
}
}
}
struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
int default_line, char ***canonical, int *not_found_ptr,
int find_all_occurrences)
{
char *p;
char *q;
struct symtab *file_symtab = NULL;
struct symtab **file_symtab_arr = NULL;
char *copy;
char *paren_pointer;
int is_quoted;
int is_quote_enclosed;
int is_objc_method = 0;
char *saved_arg = *argptr;
if (not_found_ptr)
*not_found_ptr = 0;
initialize_defaults (&default_symtab, &default_line);
if (**argptr == '*')
return decode_indirect (argptr);
set_flags (*argptr, &is_quoted, &paren_pointer);
p = locate_first_half (argptr, &is_quote_enclosed);
if (is_objc_method_format (p))
{
is_objc_method = 1;
paren_pointer = NULL;
}
if (allow_objc_selectors_flag)
{
struct symtabs_and_lines values;
if (saved_arg == NULL
|| (strcmp (saved_arg, "main") != 0
&& strcmp (saved_arg, "error") != 0))
{
values = decode_objc (argptr, funfirstline, NULL,
canonical, saved_arg);
if (values.sals != NULL)
return values;
}
}
if ((p[0] == ':' || p[0] == '.')
&& (paren_pointer == NULL || paren_pointer < p))
{
if (is_quoted)
*argptr = *argptr + 1;
if (p[0] == '.' || p[1] == ':')
return decode_compound (argptr, funfirstline, canonical,
saved_arg, p, not_found_ptr);
file_symtab_arr = symtab_from_filename (argptr, p, is_quote_enclosed,
not_found_ptr);
}
#if 0
else
{
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\000';
sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
if (sym)
{
*argptr = (*p == '\'') ? p + 1 : p;
return symbol_found (funfirstline, canonical, copy, sym,
NULL, sym_symtab);
}
}
#endif
q = *argptr;
if (*q == '-' || *q == '+')
q++;
while (*q >= '0' && *q <= '9')
q++;
if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
{
int parsed_lineno;
if (file_symtab_arr)
{
int i;
struct symtabs_and_lines final_result = {NULL, 0};
char *start_here;
for (i = 0; file_symtab_arr[i] != NULL; i++)
{
struct symtabs_and_lines this_result;
start_here = *argptr;
if (file_symtab_arr[i]->linetable == NULL)
continue;
this_result = decode_all_digits_exhaustive (&start_here,
funfirstline, default_symtab, default_line,
canonical, file_symtab_arr[i], q, &parsed_lineno);
if (this_result.nelts > 0)
{
intersect_sals (&final_result, &this_result);
}
if (this_result.sals)
xfree (this_result.sals);
}
*argptr = start_here;
if (final_result.nelts > 1)
{
int closest_line;
int i;
int num_matches;
closest_line = INT_MAX;
for (i = 0; i < final_result.nelts; i++)
{
int this_line = final_result.sals[i].line;
if (this_line == parsed_lineno)
{
closest_line = parsed_lineno;
break;
}
if (this_line > parsed_lineno
&& this_line < closest_line)
closest_line = this_line;
}
num_matches = 0;
for (i = 0; i < final_result.nelts; i++)
{
if (final_result.sals[i].line == closest_line)
{
if (i != num_matches)
final_result.sals[num_matches] = final_result.sals[i];
num_matches++;
}
}
final_result.nelts = num_matches;
}
if (final_result.nelts == 0)
{
final_result.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
memset (final_result.sals, 0, sizeof (struct symtab_and_line));
final_result.nelts = 1;
final_result.sals[0].line = parsed_lineno;
final_result.sals[0].symtab = file_symtab_arr[0];
}
return final_result;
}
else
return decode_all_digits (argptr, funfirstline, default_symtab,
default_line, canonical, NULL, q);
}
if (file_symtab_arr)
file_symtab = file_symtab_arr[0];
else
file_symtab = NULL;
if (**argptr == '$')
p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));
else if (is_quoted)
{
p = skip_quoted (*argptr);
if (p[-1] != '\'')
error (_("Unmatched single quote."));
}
else if (is_objc_method)
{
p = skip_quoted_chars (*argptr, NULL, "");
}
else if (paren_pointer != NULL)
{
p = paren_pointer + 1;
}
else
{
p = skip_quoted (*argptr);
}
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
if (p != *argptr
&& copy[0]
&& copy[0] == copy[p - *argptr - 1]
&& strchr (get_gdb_completer_quote_characters (), copy[0]) != NULL)
{
copy[p - *argptr - 1] = '\0';
copy++;
}
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
if (*copy == '$')
return decode_dollar (copy, funfirstline, default_symtab,
canonical, file_symtab);
if (find_all_occurrences)
return decode_all_variables (copy, funfirstline, !is_quoted, canonical,
file_symtab, not_found_ptr);
else
return decode_variable (copy, funfirstline, !is_quoted, canonical,
file_symtab, not_found_ptr);
}
static void
initialize_defaults (struct symtab **default_symtab, int *default_line)
{
if (*default_symtab == 0)
{
struct symtab_and_line cursal =
get_current_source_symtab_and_line ();
*default_symtab = cursal.symtab;
*default_line = cursal.line;
}
}
static void
set_flags (char *arg, int *is_quoted, char **paren_pointer)
{
char *ii;
int has_if = 0;
if ((ii = strstr (arg, " if ")) != NULL ||
(ii = strstr (arg, "\tif ")) != NULL ||
(ii = strstr (arg, " if\t")) != NULL ||
(ii = strstr (arg, "\tif\t")) != NULL ||
(ii = strstr (arg, " if(")) != NULL ||
(ii = strstr (arg, "\tif( ")) != NULL)
has_if = 1;
if (has_if)
{
*ii = '\0';
}
*is_quoted = (*arg
&& strchr (get_gdb_completer_quote_characters (),
*arg) != NULL);
*paren_pointer = strchr (arg, '(');
if (*paren_pointer != NULL)
*paren_pointer = strrchr (*paren_pointer, ')');
if (has_if)
*ii = ' ';
}
static struct symtabs_and_lines
decode_indirect (char **argptr)
{
struct symtabs_and_lines values;
CORE_ADDR pc;
(*argptr)++;
pc = parse_and_eval_address_1 (argptr);
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
values.sals[0] = find_pc_line (pc, 0);
values.sals[0].pc = pc;
values.sals[0].section = find_pc_overlay (pc);
return values;
}
static char *
locate_first_half (char **argptr, int *is_quote_enclosed)
{
char *ii;
char *p, *p1;
int has_comma;
ii = find_toplevel_char (*argptr, ',');
has_comma = (ii != 0);
if (has_comma)
{
*ii = '\0';
}
p = *argptr;
if (p[0] == '"')
{
*is_quote_enclosed = 1;
(*argptr)++;
p++;
}
else
*is_quote_enclosed = 0;
for (; *p; p++)
{
if (p[0] == '<')
{
char *temp_end = find_template_name_end (p);
if (!temp_end)
error (_("malformed template specification in command"));
p = temp_end;
}
if (is_objc_method_format (p))
{
break;
}
if (!*p
|| p[0] == '\t'
|| ((p[0] == ':')
&& ((p[1] == ':') || (strchr (p + 1, ':') == NULL)))
|| ((p[0] == ' ') && !*is_quote_enclosed))
break;
if (p[0] == '.' && strchr (p, ':') == NULL)
{
for (p1 = p; *p1; p1++)
{
if (*p1 == '.')
p = p1;
}
break;
}
}
while (p[0] == ' ' || p[0] == '\t')
p++;
if (*is_quote_enclosed)
{
char *closing_quote = strchr (p - 1, '"');
if (closing_quote && closing_quote[1] == '\0')
*closing_quote = '\0';
}
if (has_comma)
*ii = ',';
return p;
}
struct symtabs_and_lines
decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
char ***canonical, char *saved_arg)
{
struct symtabs_and_lines values;
struct symbol **sym_arr = NULL;
struct symbol *sym = NULL;
char *copy = NULL;
struct block *block = NULL;
int i1 = 0;
int i2 = 0;
values.sals = NULL;
values.nelts = 0;
if (file_symtab != NULL)
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
else
block = get_selected_block (0);
copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2);
if (i1 > 0)
{
sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
sym_arr[i1] = 0;
copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
*argptr = copy;
}
if (i1 == 1)
{
if (i2 > 0)
{
sym = sym_arr[0];
}
else
{
if (SYMBOL_BFD_SECTION (sym_arr[0]) != 0)
sym = find_pc_sect_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]),
SYMBOL_BFD_SECTION (sym_arr[0]));
else
sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]), SYMBOL_LINKAGE_NAME (sym)) != 0)
{
warning (_("debugging symbol \"%s\" does not match selector; ignoring"), SYMBOL_LINKAGE_NAME (sym));
sym = NULL;
}
}
values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
values.sals[0] = find_function_start_sal (sym, funfirstline);
build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical);
}
else
{
values.sals[0].symtab = 0;
values.sals[0].line = 0;
values.sals[0].end = 0;
values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
if (funfirstline)
{
if (SKIP_PROLOGUE_ADDR_CTX_P ())
{
struct address_context sym_addr_ctx;
init_address_context (&sym_addr_ctx);
sym_addr_ctx.address = values.sals[0].pc;
sym_addr_ctx.symbol = sym;
sym_addr_ctx.bfd_section = SYMBOL_BFD_SECTION (sym_arr[0]);
values.sals[0].pc = SKIP_PROLOGUE_ADDR_CTX (&sym_addr_ctx);
}
else
{
values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
}
}
values.sals[0].section = SYMBOL_BFD_SECTION (sym_arr[0]);
}
return values;
}
if (i1 > 1)
{
int accept_all;
if (ui_out_is_mi_like_p (uiout))
accept_all = 1;
else
accept_all = 0;
return decode_line_2 (sym_arr, i1, i2, funfirstline, accept_all, canonical);
}
return values;
}
static struct symtabs_and_lines
decode_compound (char **argptr, int funfirstline, char ***canonical,
char *saved_arg, char *p, int *not_found_ptr)
{
char *p2;
char *saved_arg2 = *argptr;
char *temp_end;
struct symbol *sym;
struct symtab *sym_symtab;
char *copy;
struct symbol *sym_class;
struct type *t;
if (p[0] == ':'
&& ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
saved_arg2 += 2;
p2 = p;
while (1)
{
p = p2 + 1;
while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
{
if (p[0] == '<')
{
temp_end = find_template_name_end (p);
if (!temp_end)
error (_("malformed template specification in command"));
p = temp_end;
}
else if ((p[0] == ':') && (p[1] == ':'))
break;
else
p++;
}
if (*p != ':')
break;
p2 = p;
*argptr = saved_arg2;
}
sym_class = lookup_prefix_sym (argptr, p2);
if (sym_class &&
(t = check_typedef (SYMBOL_TYPE (sym_class)),
(TYPE_CODE (t) == TYPE_CODE_STRUCT
|| TYPE_CODE (t) == TYPE_CODE_UNION)))
{
if (**argptr
&& strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL)
{
p = skip_quoted (*argptr);
*argptr = *argptr + 1;
}
else
{
p = *argptr;
while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
p++;
}
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\0';
if (p != *argptr
&& copy[p - *argptr - 1]
&& strchr (get_gdb_completer_quote_characters (),
copy[p - *argptr - 1]) != NULL)
copy[p - *argptr - 1] = '\0';
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
return find_method (funfirstline, canonical, saved_arg,
copy, t, sym_class, not_found_ptr);
}
copy = (char *) alloca (p - saved_arg2 + 1);
memcpy (copy, saved_arg2, p - saved_arg2);
copy[p - saved_arg2] = '\000';
*argptr = (*p == '\'') ? p + 1 : p;
{
int syms_found = 0;
struct symbol_search *sym_list = NULL;
syms_found = lookup_symbol_all (copy, 0, VAR_DOMAIN, 0, &sym_symtab,
&sym_list);
if (syms_found)
return symbols_found (funfirstline, canonical, copy, sym_list,
sym_symtab);
}
if (not_found_ptr)
*not_found_ptr = 1;
cplusplus_error (saved_arg,
"Can't find member of namespace, class, struct, or union named \"%s\"\n",
copy);
}
static struct symbol *
lookup_prefix_sym (char **argptr, char *p)
{
char *p1;
char *copy;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = 0;
p = p1 + (p1[0] == ':' ? 2 : 1);
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
return lookup_symbol (copy, 0, STRUCT_DOMAIN, 0,
(struct symtab **) NULL);
}
static struct symtabs_and_lines
find_method (int funfirstline, char ***canonical, char *saved_arg,
char *copy, struct type *t, struct symbol *sym_class,
int *not_found_ptr)
{
struct symtabs_and_lines values;
struct symbol *sym = 0;
int i1;
int sym_arr_size = total_number_of_methods (t);
struct symbol **sym_arr = xcalloc (sym_arr_size,
sizeof (struct symbol *));
i1 = collect_methods (copy, t, &sym_arr, &sym_arr_size);
if (i1 == 1)
{
sym = sym_arr[0];
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
values.sals[0] = find_function_start_sal (sym,
funfirstline);
}
else
{
values.nelts = 0;
}
xfree (sym_arr);
return values;
}
if (i1 > 0)
{
int accept_all;
if (ui_out_is_mi_like_p (uiout))
accept_all = 1;
else
accept_all = 0;
values = decode_line_2 (sym_arr, i1, i1, funfirstline, accept_all,
canonical);
xfree (sym_arr);
return values;
}
else
{
char *tmp;
if (is_operator_name (copy))
{
tmp = (char *) alloca (strlen (copy + 3) + 9);
strcpy (tmp, "operator ");
strcat (tmp, copy + 3);
}
else
tmp = copy;
if (not_found_ptr)
*not_found_ptr = 1;
xfree (sym_arr);
if (tmp[0] == '~')
cplusplus_error (saved_arg,
"the class `%s' does not have destructor defined\n",
SYMBOL_PRINT_NAME (sym_class));
else
cplusplus_error (saved_arg,
"the class %s does not have any method named %s\n",
SYMBOL_PRINT_NAME (sym_class), tmp);
}
}
static int
collect_methods (char *copy, struct type *t,
struct symbol ***sym_arr, int *sym_arr_size)
{
int i1 = 0;
int arr_pos = 0;
int syms_found = 0;
struct symbol_search *sym_list = NULL;
if (destructor_name_p (copy, t))
{
int m_index, f_index;
if (get_destructor_fn_field (t, &m_index, &f_index))
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
char *phys_name = TYPE_FN_FIELD_PHYSNAME (f, f_index);
if (phys_name[0] != '_')
{
char *demangled_name = alloca (strlen (TYPE_NAME (t)) +
strlen (phys_name) + 3);
sprintf (demangled_name, "%s::%s", TYPE_NAME (t), phys_name);
syms_found = lookup_symbol_all (demangled_name, NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL,
&sym_list);
}
else
syms_found = lookup_symbol_all (phys_name, NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL,
&sym_list);
if (syms_found)
{
int j;
int num_syms = 0;
struct symbol_search *cur;
remove_duplicate_symbols (*sym_arr, arr_pos, &sym_list);
for (cur = sym_list; cur; cur = cur->next)
num_syms++;
if (num_syms > *sym_arr_size)
{
int k;
*sym_arr = xrealloc (*sym_arr,
num_syms * sizeof (struct symbol *));
for (k = *sym_arr_size; k < num_syms; k++)
(*sym_arr)[k] = NULL;
*sym_arr_size = num_syms;
}
i1 = num_syms;
for (j = 0, cur = sym_list; j < num_syms && cur;
j++, cur = cur->next)
(*sym_arr)[j] = cur->symbol;
}
}
}
else
i1 = find_methods (t, copy, sym_arr, sym_arr_size, &arr_pos);
return i1;
}
static struct symtab **
symtab_from_filename (char **argptr, char *p, int is_quote_enclosed,
int *not_found_ptr)
{
char *p1;
char *copy;
struct symtab **file_symtab_arr;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
if ((*p == '"') && is_quote_enclosed)
--p;
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
if (is_quote_enclosed && copy[p - *argptr - 1] == '"')
copy[p - *argptr - 1] = 0;
else
copy[p - *argptr] = 0;
file_symtab_arr = lookup_symtab_all (copy);
if (file_symtab_arr == 0)
{
if (not_found_ptr)
*not_found_ptr = 1;
if (!have_full_symbols () && !have_partial_symbols ())
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. Use the \"file\" command."));
throw_error (NOT_FOUND_ERROR, _("No source file named %s."), copy);
}
p = p1 + 1;
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
return file_symtab_arr;
}
static struct symtabs_and_lines
decode_all_digits_exhaustive (char **argptr, int funfirstline,
struct symtab *default_symtab,
int default_line, char ***canonical,
struct symtab *file_symtab, char *q,
int *parsed_lineno)
{
struct symtabs_and_lines values;
int nvalues_allocated;
int lineno;
enum sign
{
none, plus, minus
}
sign = none;
int need_canonical = (file_symtab == 0) ? 1 : 0;
if (file_symtab == 0 && default_symtab == 0)
{
set_default_source_symtab_and_line ();
initialize_defaults (&default_symtab, &default_line);
}
if (**argptr == '+')
sign = plus, (*argptr)++;
else if (**argptr == '-')
sign = minus, (*argptr)++;
lineno = atoi (*argptr);
switch (sign)
{
case plus:
if (q == *argptr)
lineno = 5;
if (file_symtab == 0)
lineno = default_line + lineno;
break;
case minus:
if (q == *argptr)
lineno = 15;
if (file_symtab == 0)
lineno = default_line - lineno;
else
lineno = 1;
break;
case none:
break;
}
*parsed_lineno = lineno;
values.nelts = 0;
values.sals =
(struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
nvalues_allocated = 1;
values.sals[0].pc = 0;
values.sals[0].end = 0;
while (*q == ' ' || *q == '\t')
q++;
*argptr = q;
if (file_symtab == 0)
file_symtab = default_symtab;
{
struct linetable *l;
struct blockvector *cur_blockvector, *new_blockvector;;
int cur_index, new_index;
int exact = 0;
int best = 0;
int i;
l = LINETABLE (file_symtab);
do_with_best:
cur_blockvector = NULL;
cur_index = -2;
for (i = 0; i < l->nitems; i++)
{
struct linetable_entry *item = &(l->item[i]);
if (item->line == lineno)
{
exact = 1;
new_blockvector = blockvector_for_pc_sect (item->pc, NULL,
&new_index, file_symtab);
if (new_blockvector == cur_blockvector && new_index == cur_index)
continue;
else
{
struct symtab_and_line *sal;
exact = 1;
cur_blockvector = new_blockvector;
cur_index = new_index;
if (values.nelts == nvalues_allocated)
{
nvalues_allocated *= 2;
values.sals = (struct symtab_and_line *)
xrealloc (values.sals, nvalues_allocated * sizeof (struct symtab_and_line));
}
sal = &(values.sals[values.nelts++]);
init_sal (sal);
sal->line = lineno;
sal->pc = item->pc;
sal->symtab = file_symtab;
}
}
if (!exact && item->line > lineno && (best == 0 || item->line < best))
{
best = item->line;
}
}
if (!exact)
{
if (best > 0)
{
lineno = best;
goto do_with_best;
}
else
{
}
}
if (funfirstline)
{
int i;
for (i = 0; i < values.nelts; i++)
{
struct symtab_and_line *val = &(values.sals[i]);
struct symbol *func_sym;
if (val->symtab && val->symtab->objfile)
{
struct cleanup *restrict_cleanup;
restrict_cleanup =
make_cleanup_restrict_to_objfile
(val->symtab->objfile);
func_sym = find_pc_function (val->pc);
do_cleanups (restrict_cleanup);
}
else
{
func_sym = find_pc_function (val->pc);
}
if (func_sym)
{
struct symtab_and_line sal;
sal = find_function_start_sal (func_sym, 1);
if (val->symtab == sal.symtab
&&val->line <= sal.line)
val->pc = sal.pc;
}
}
}
}
if (need_canonical && values.nelts > 0)
build_canonical_line_spec (values.sals, NULL, canonical);
return values;
}
static struct symtabs_and_lines
decode_all_digits (char **argptr, int funfirstline,
struct symtab *default_symtab,
int default_line, char ***canonical,
struct symtab *file_symtab, char *q)
{
struct symtabs_and_lines values;
struct symtab_and_line val;
enum sign
{
none, plus, minus
}
sign = none;
int need_canonical = (file_symtab == 0) ? 1 : 0;
init_sal (&val);
if (file_symtab == 0 && default_symtab == 0)
{
set_default_source_symtab_and_line ();
initialize_defaults (&default_symtab, &default_line);
}
if (**argptr == '+')
sign = plus, (*argptr)++;
else if (**argptr == '-')
sign = minus, (*argptr)++;
val.line = atoi (*argptr);
switch (sign)
{
case plus:
if (q == *argptr)
val.line = 5;
if (file_symtab == 0)
val.line = default_line + val.line;
break;
case minus:
if (q == *argptr)
val.line = 15;
if (file_symtab == 0)
val.line = default_line - val.line;
else
val.line = 1;
break;
case none:
break;
}
while (*q == ' ' || *q == '\t')
q++;
*argptr = q;
if (file_symtab == 0)
file_symtab = default_symtab;
val.symtab = find_line_symtab (file_symtab, val.line, NULL, NULL);
if (val.symtab == 0)
val.symtab = file_symtab;
val.pc = 0;
if (funfirstline)
{
CORE_ADDR pc = 0;
if (find_line_pc (val.symtab, val.line, &pc))
{
struct symbol *func_sym;
struct symtab_and_line sal;
if (val.symtab && val.symtab->objfile)
{
struct cleanup *restrict_cleanup;
restrict_cleanup =
make_cleanup_restrict_to_objfile
(val.symtab->objfile);
func_sym = find_pc_function (pc);
do_cleanups (restrict_cleanup);
}
else
{
func_sym = find_pc_function (pc);
}
if (func_sym)
{
sal = find_function_start_sal (func_sym, 1);
if (val.line <= sal.line)
val.pc = sal.pc;
}
}
}
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.sals[0] = val;
values.nelts = 1;
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
return values;
}
static struct symtabs_and_lines
decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
char ***canonical, struct symtab *file_symtab)
{
struct value *valx;
int index = 0;
int need_canonical = 0;
struct symtabs_and_lines values;
struct symtab_and_line val;
char *p;
struct symbol *sym;
struct symtab *sym_symtab;
struct minimal_symbol *msymbol;
p = (copy[1] == '$') ? copy + 2 : copy + 1;
while (*p >= '0' && *p <= '9')
p++;
if (!*p)
{
sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
valx = access_value_history ((copy[1] == '$') ? -index : index);
if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
error (_("History values used in line specs must have integer values."));
}
else
{
sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
file_symtab = (struct symtab *) 0;
need_canonical = 1;
if (sym)
return symbol_found (funfirstline, canonical, copy, sym,
NULL, sym_symtab);
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
if (msymbol)
return minsym_found (funfirstline, 0, msymbol, canonical);
need_canonical = (file_symtab == 0) ? 1 : 0;
valx = value_of_internalvar (lookup_internalvar (copy + 1));
if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
error (_("Convenience variables used in line specs must have integer values."));
}
init_sal (&val);
val.symtab = file_symtab ? file_symtab : default_symtab;
val.line = value_as_long (valx);
val.pc = 0;
values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
values.sals[0] = val;
values.nelts = 1;
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
return values;
}
static struct symtabs_and_lines
decode_variable (char *copy, int funfirstline, int equivalencies,
char ***canonical, struct symtab *file_symtab,
int *not_found_ptr)
{
struct symbol *sym;
struct symtab *sym_symtab;
struct minimal_symbol *msymbol;
sym = lookup_symbol (copy,
(file_symtab
? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
STATIC_BLOCK)
: get_selected_block (0)),
VAR_DOMAIN, 0, &sym_symtab);
if (sym != NULL)
return symbol_found (funfirstline, canonical, copy, sym,
file_symtab, sym_symtab);
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
if (msymbol != NULL)
return minsym_found (funfirstline, equivalencies, msymbol, canonical);
if (!have_full_symbols () &&
!have_partial_symbols () && !have_minimal_symbols ())
{
if (not_found_ptr)
*not_found_ptr = 1;
error (_("No symbol table is loaded. Use the \"file\" command."));
}
if (not_found_ptr)
*not_found_ptr = 1;
if (file_symtab == NULL)
throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
else
throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined in file %s."),
copy, file_symtab->filename);
}
static struct symtabs_and_lines
decode_all_variables (char *copy, int funfirstline, int equivalencies,
char ***canonical, struct symtab *file_symtab,
int *not_found_ptr)
{
struct symtab *sym_symtab = NULL;
struct minimal_symbol *msymbol = NULL;
struct symbol_search *sym_list = NULL;
struct symbol_search *outer_current;
struct symbol_search *cur;
struct symbol_search *prev;
int syms_found = 0;
syms_found = lookup_symbol_all
(copy, (file_symtab
? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
STATIC_BLOCK)
: get_selected_block (0)),
VAR_DOMAIN, 0, &sym_symtab, &sym_list);
if (!syms_found)
msymbol = lookup_minimal_symbol_all (copy, NULL, NULL, &sym_list);
if (!syms_found && !msymbol)
{
if (!have_full_symbols () &&
!have_partial_symbols () && !have_minimal_symbols ())
{
if (not_found_ptr)
*not_found_ptr = 1;
error (_("No symbol table is loaded. Use the \"file\" command."));
}
if (not_found_ptr)
*not_found_ptr = 1;
if (file_symtab == NULL)
throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
else
throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined in file %s."),
copy, file_symtab->filename);
}
gdb_assert (sym_list != NULL);
for (outer_current = sym_list;
outer_current;
outer_current = outer_current->next)
for (prev = outer_current, cur = prev->next; cur; )
{
if (cur->symbol && cur->symbol == prev->symbol)
prev->next = cur->next;
else if (cur->msymbol && cur->msymbol == prev->msymbol)
prev->next = cur->next;
else
prev = cur;
cur = cur->next;
}
if (syms_found)
return symbols_found (funfirstline, canonical, copy, sym_list, file_symtab);
else
return minsyms_found (funfirstline, equivalencies, sym_list, canonical);
}
static struct symtabs_and_lines
symbols_found (int funfirstline, char ***canonical, char *copy,
struct symbol_search *sym_list, struct symtab *file_symtab)
{
struct symbol_search *current;
struct symtabs_and_lines values;
char **canonical_arr;
int num_syms = 0;
int i;
for (current = sym_list; current; current = current->next)
num_syms++;
values.sals = (struct symtab_and_line *) xmalloc (num_syms *
sizeof (struct symtab_and_line));
values.nelts = num_syms;
canonical_arr = (char **) xmalloc (num_syms * sizeof (char *));
memset (canonical_arr, 0, num_syms * sizeof (char *));
*canonical = canonical_arr;
for (current = sym_list, i = 0; current; current = current->next, i++)
{
struct symbol *sym = current->symbol;
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
values.sals[i] = find_function_start_sal (sym, funfirstline);
if (values.sals[i].symtab == 0)
error (_("Line number not known for symbol \"%s\""), copy);
if (file_symtab == 0)
{
struct blockvector *bv = BLOCKVECTOR (values.sals[i].symtab);
struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
{
char *canonical_name;
struct symtab *s = values.sals[i].symtab;
if (s && s->filename)
{
if (copy)
{
canonical_name = xmalloc (strlen (s->filename) +
strlen (copy) + 2);
sprintf (canonical_name, "%s:%s", s->filename,
copy);
}
else
{
canonical_name = xmalloc (strlen (s->filename) + 30);
sprintf (canonical_name, "%s:%d", s->filename,
values.sals[i].line);
}
canonical_arr[i] = canonical_name;
}
}
}
}
else
{
if (funfirstline)
error (_("\"%s\" is not a function"), copy);
else if (SYMBOL_LINE (sym) != 0)
{
values.sals[i].symtab = current->symtab;
values.sals[i].line = SYMBOL_LINE (sym);
}
else
error (_("Line number not known for symbol \"%s\""), copy);
}
}
return values;
}
static struct symtabs_and_lines
symbol_found (int funfirstline, char ***canonical, char *copy,
struct symbol *sym, struct symtab *file_symtab,
struct symtab *sym_symtab)
{
struct symtabs_and_lines values;
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.sals[0] = find_function_start_sal (sym, funfirstline);
values.nelts = 1;
if (file_symtab == 0)
{
struct blockvector *bv = BLOCKVECTOR (sym_symtab);
struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
build_canonical_line_spec (values.sals, copy, canonical);
}
return values;
}
else
{
if (funfirstline)
error (_("\"%s\" is not a function"), copy);
else if (SYMBOL_LINE (sym) != 0)
{
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.nelts = 1;
memset (&values.sals[0], 0, sizeof (values.sals[0]));
values.sals[0].symtab = sym_symtab;
values.sals[0].line = SYMBOL_LINE (sym);
return values;
}
else
error (_("Line number not known for symbol \"%s\""), copy);
}
}
static struct symtabs_and_lines
minsyms_found (int funfirstline, int equivalencies,
struct symbol_search *sym_list, char ***canonical)
{
struct symbol_search *current;
struct minimal_symbol **equiv_msymbols;
struct minimal_symbol **pointer;
struct symtabs_and_lines values;
struct cleanup *equiv_cleanup;
int nsymbols = 0;
int eq_symbols = 0;
int i;
int j;
for (current = sym_list; current; current = current->next)
nsymbols++;
equiv_msymbols = NULL;
if (equivalencies)
{
equiv_msymbols = find_equivalent_msymbol (sym_list->msymbol);
if (equiv_msymbols != NULL)
{
for (pointer = equiv_msymbols; *pointer != NULL; eq_symbols++, pointer++)
;
equiv_cleanup = make_cleanup (xfree, equiv_msymbols);
}
else
equiv_cleanup = make_cleanup (null_cleanup, NULL);
}
else
equiv_cleanup = make_cleanup (null_cleanup, NULL);
values.sals = (struct symtab_and_line *)
xmalloc ((nsymbols + eq_symbols) * sizeof (struct symtab_and_line));
for (current = sym_list, i = 0; current; current = current->next, i++)
{
values.sals[i] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (current->msymbol),
current->msymbol->ginfo.bfd_section, 0);
values.sals[i].section = SYMBOL_BFD_SECTION (current->msymbol);
if (funfirstline)
{
values.sals[i].pc += DEPRECATED_FUNCTION_START_OFFSET;
if (SKIP_PROLOGUE_ADDR_CTX_P ())
{
struct address_context sym_addr_ctx;
init_address_context (&sym_addr_ctx);
sym_addr_ctx.address = values.sals[i].pc;
sym_addr_ctx.bfd_section = values.sals[i].section;
sym_addr_ctx.sal = values.sals[i];
sym_addr_ctx.msymbol = current->msymbol;
values.sals[i].pc = SKIP_PROLOGUE_ADDR_CTX (&sym_addr_ctx);
}
else
{
values.sals[i].pc = SKIP_PROLOGUE (values.sals[i].pc);
}
}
}
for (j = 0; j < eq_symbols; j++, i++)
{
struct minimal_symbol *msym;
msym = equiv_msymbols[j];
values.sals[i] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msym),
msym->ginfo.bfd_section, 0);
values.sals[i].section = SYMBOL_BFD_SECTION (msym);
if (funfirstline)
{
values.sals[i].pc += DEPRECATED_FUNCTION_START_OFFSET;
if (SKIP_PROLOGUE_ADDR_CTX_P ())
{
struct address_context sym_addr_ctx;
init_address_context (&sym_addr_ctx);
sym_addr_ctx.address = values.sals[i].pc;
sym_addr_ctx.bfd_section = values.sals[i].section;
sym_addr_ctx.sal = values.sals[i];
sym_addr_ctx.msymbol = msym;
values.sals[i].pc = SKIP_PROLOGUE_ADDR_CTX (&sym_addr_ctx);
}
else
{
values.sals[i].pc = SKIP_PROLOGUE (values.sals[i].pc);
}
}
}
if (eq_symbols && canonical != (char ***) NULL)
{
char **canonical_arr;
canonical_arr = (char **) xmalloc ((eq_symbols + nsymbols) * sizeof (char *));
*canonical = canonical_arr;
for (current = sym_list, i = 0; current; current = current->next, i++)
{
struct minimal_symbol *msym;
msym = current->msymbol;
xasprintf (&canonical_arr[i], "'%s'", SYMBOL_LINKAGE_NAME (msym));
}
for (j = 0; j < eq_symbols; j++)
{
struct minimal_symbol *msym;
msym = equiv_msymbols[j];
xasprintf (&canonical_arr[j+i], "'%s'", SYMBOL_LINKAGE_NAME (msym));
}
}
values.nelts = nsymbols + eq_symbols;
do_cleanups (equiv_cleanup);
return values;
}
static struct symtabs_and_lines
minsym_found (int funfirstline, int equivalencies,
struct minimal_symbol *msymbol, char ***canonical)
{
struct symtabs_and_lines values;
struct minimal_symbol **equiv_msymbols = NULL;
struct minimal_symbol **pointer;
int nsymbols, i;
struct cleanup *equiv_cleanup;
if (equivalencies)
equiv_msymbols = find_equivalent_msymbol (msymbol);
nsymbols = 1;
if (equiv_msymbols != NULL)
{
for (pointer = equiv_msymbols; *pointer != NULL;
nsymbols++, pointer++)
;
equiv_cleanup = make_cleanup (xfree, equiv_msymbols);
}
else
equiv_cleanup = make_cleanup (null_cleanup, NULL);
values.sals = (struct symtab_and_line *)
xmalloc (nsymbols * sizeof (struct symtab_and_line));
for (i = 0; i < nsymbols; i++)
{
struct minimal_symbol *msym;
if (i == 0)
msym = msymbol;
else
msym = equiv_msymbols[i - 1];
values.sals[i] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msym),
msym->ginfo.bfd_section, 0);
values.sals[i].section = SYMBOL_BFD_SECTION (msym);
if (funfirstline)
{
values.sals[i].pc += DEPRECATED_FUNCTION_START_OFFSET;
if (SKIP_PROLOGUE_ADDR_CTX_P ())
{
struct address_context sym_addr_ctx;
init_address_context (&sym_addr_ctx);
sym_addr_ctx.address = values.sals[i].pc;
sym_addr_ctx.bfd_section = values.sals[i].section;
sym_addr_ctx.sal = values.sals[i];
sym_addr_ctx.msymbol = msym;
values.sals[i].pc = SKIP_PROLOGUE_ADDR_CTX (&sym_addr_ctx);
}
else
{
values.sals[i].pc = SKIP_PROLOGUE (values.sals[i].pc);
}
}
}
if (nsymbols > 1 && canonical != (char ***) NULL)
{
char **canonical_arr;
canonical_arr = (char **) xmalloc (nsymbols * sizeof (char *));
*canonical = canonical_arr;
for (i = 0; i < nsymbols; i++)
{
struct minimal_symbol *msym;
if (i == 0)
msym = msymbol;
else
msym = equiv_msymbols[i - 1];
xasprintf (&canonical_arr[i], "'%s'", SYMBOL_LINKAGE_NAME (msym));
}
}
values.nelts = nsymbols;
do_cleanups (equiv_cleanup);
return values;
}
void
reset_allow_objc_selectors_flag (PTR dummy)
{
allow_objc_selectors_flag = 1;
}