#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"
extern int metrowerks_ignore_breakpoint_errors_flag;
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);
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 **);
static int add_matching_methods (int method_counter, struct type *t,
struct symbol **sym_arr);
static int add_constructors (int method_counter, struct type *t,
struct symbol **sym_arr);
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 (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 symbol_found (int funfirstline,
char ***canonical,
char *copy,
struct symbol *sym,
struct symtab *file_symtab,
struct symtab *sym_symtab);
static struct
symtabs_and_lines minsym_found (int funfirstline, int equivalencies,
struct minimal_symbol *msymbol,
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 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 + i1);
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 + i1);
}
}
if (i1 == 0)
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
do_cleanups (old_chain);
return i1;
}
static int
add_matching_methods (int method_counter, struct type *t,
struct symbol **sym_arr)
{
int field_counter;
int i1 = 0;
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))
{
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;
sym_arr[i1] = lookup_symbol (phys_name,
NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
else
{
}
}
return i1;
}
static int
add_constructors (int method_counter, struct type *t,
struct symbol **sym_arr)
{
int field_counter;
int i1 = 0;
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;
sym_arr[i1] = lookup_symbol (phys_name,
NULL, VAR_DOMAIN,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
}
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?");
}
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]);
if (funfirstline)
values.sals[i].pc = SKIP_PROLOGUE (values.sals[i].pc);
values.sals[i].section = SYMBOL_BFD_SECTION (sym_arr[i]);
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;
}
struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
int default_line, char ***canonical, int *not_found_ptr)
{
char *p;
char *q;
struct symtab *file_symtab = 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;
values = decode_objc (argptr, funfirstline, NULL,
canonical, saved_arg);
if (values.sals != NULL)
return values;
}
if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
{
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 = 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 == ','))
return decode_all_digits (argptr, funfirstline, default_symtab, default_line,
canonical, file_symtab, q);
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);
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
{
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)
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)
{
struct symtabs_and_lines values;
char *p2;
char *saved_arg2 = *argptr;
char *temp_end;
struct symbol *sym;
struct symtab *sym_symtab;
char *copy;
struct symbol *sym_class;
struct symbol **sym_arr;
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;
sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
if (sym)
return symbol_found (funfirstline, canonical, copy, sym,
NULL, 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;
struct symbol **sym_arr = alloca (total_number_of_methods (t)
* sizeof (struct symbol *));
i1 = collect_methods (copy, t, sym_arr);
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;
}
return values;
}
if (i1 > 0)
{
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, i1, funfirstline, accept_all, canonical);
}
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;
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 i1 = 0;
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);
sym_arr[i1] =
lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
NULL, VAR_DOMAIN, (int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
}
}
else
i1 = find_methods (t, copy, sym_arr);
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;
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 = lookup_symtab (copy);
if (file_symtab == 0)
{
if (not_found_ptr)
{
*not_found_ptr = 1;
error_silent ("No source file named %s.", copy);
}
else if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
else
error ("No source file named %s.", copy);
}
p = p1 + 1;
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
return file_symtab;
}
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 (metrowerks_ignore_breakpoint_errors_flag)
{
struct symtabs_and_lines values;
values.sals = NULL;
return values;
}
if (not_found_ptr)
{
*not_found_ptr = 1;
error_silent ("Function \"%s\" not defined.", copy);
}
if (file_symtab == NULL)
error ("Function \"%s\" not defined.", copy);
else
error ("Function \"%s\" not defined in file %s.",
copy, file_symtab->filename);
}
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
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 += FUNCTION_START_OFFSET;
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;
}