#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"
extern int metrowerks_ignore_breakpoint_errors_flag;
extern int allow_objc_selectors_flag;
extern char *find_template_name_end (char *);
extern char *operator_chars (char *, char **);
static void cplusplus_error (const char *name, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
static int total_number_of_methods (struct type *type);
static int find_methods (struct type *, char *, struct symbol **);
static void build_canonical_line_spec (struct symtab_and_line *,
char *, char ***);
static char *find_toplevel_char (char *s, char c);
static struct symtabs_and_lines decode_line_2 (struct symbol *[],
int, int, int, char ***);
static 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;
struct symbol *sym_class;
char *class_name = type_name_no_tag (t);
if (class_name
&& (lookup_symbol (class_name, (struct block *) NULL,
STRUCT_NAMESPACE, (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)
{
int field_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)
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_NAMESPACE,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
else
{
}
}
else if (strncmp (class_name, name, name_len) == 0
&& (class_name[name_len] == '\0'
|| class_name[name_len] == '<'))
{
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_NAMESPACE,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
}
}
}
}
if (i1 == 0)
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + 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)
{
if ((strstr (symname, "::") != NULL)
|| (((symname[0] == '-') || (symname[0] == '+')) && (symname[1] == '[')))
{
canonical_name = xmalloc (strlen (symname) + 1);
sprintf (canonical_name, "%s", symname);
}
else
{
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 struct symtabs_and_lines
decode_line_2 (struct symbol *sym_arr[], int nelts, int nsym, int funfirstline,
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;
}
printf_unfiltered ("[0] cancel\n[1] all\n");
for (i = 0; i < nsym; i++)
{
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);
printf_unfiltered ("[%d] %s at %s:%d\n",
(i + 2),
SYMBOL_SOURCE_NAME (sym_arr[i]),
values.sals[i].symtab->filename,
values.sals[i].line);
}
else
printf_filtered ("[%d] %s\n",
(i + 2),
SYMBOL_SOURCE_NAME (sym_arr[i]) ?
SYMBOL_SOURCE_NAME (sym_arr[i]) : "?HERE?");
}
if (nelts != nsym)
printf_filtered ("\nNon-debugging symbols:\n");
for (i = nsym; i < nelts; i++)
{
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]);
printf_filtered ("[%d] %s\n",
(i + 2),
SYMBOL_SOURCE_NAME (sym_arr[i]));
}
if ((prompt = getenv ("PS2")) == NULL)
{
prompt = "> ";
}
args = command_line_input (prompt, 0, "overload-choice");
if (args == 0 || *args == 0)
error_no_arg ("one or more choice numbers");
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 ("cancelled");
else if (num == 1)
{
if (canonical_arr)
{
for (i = 0; i < nelts; i++)
{
if (canonical_arr[i] == NULL)
{
if (values.sals[i].symtab)
{
symname = xmalloc
(strlen (values.sals[i].symtab->filename) + 30);
sprintf (symname, "%s:%d",
values.sals[i].symtab->filename,
values.sals[i].line);
}
else
{
symname = 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)
{
if (values.sals[num].symtab)
{
symname = xmalloc
(strlen (values.sals[num].symtab->filename) + 30);
sprintf (symname, "%s:%d",
values.sals[num].symtab->filename,
values.sals[num].line);
}
else
{
symname = SYMBOL_NAME (sym_arr[num]);
}
canonical_arr[i] = savestring (symname, strlen (symname));
}
return_values.sals[i++] = values.sals[num];
values.sals[num].pc = 0;
}
else
{
printf_filtered ("duplicate request for %d ignored.\n", num + 2);
}
}
args = arg1;
while (*args == ' ' || *args == '\t')
args++;
}
return_values.nelts = i;
discard_cleanups (old_chain);
return return_values;
}
static struct symtabs_and_lines
decode_line_1a (char **argptr, int funfirstline, struct symtab *default_symtab,
int default_line, char ***canonical)
{
struct symtabs_and_lines values;
struct symtab_and_line val;
register char *p, *p1;
char *q, *pp, *ii, *p2;
#if 0
char *q1;
#endif
register struct symtab *s;
register struct symbol *sym;
struct symtab *sym_symtab;
register CORE_ADDR pc;
register struct minimal_symbol *msymbol;
char *copy;
struct symbol *sym_class;
unsigned int i1, i2;
int is_quoted;
int is_quote_enclosed;
int has_parens;
int has_comma = 0;
struct symbol **sym_arr;
struct type *t;
char *saved_arg = *argptr;
extern char *gdb_completer_quote_characters;
INIT_SAL (&val);
if (default_symtab == 0)
{
struct symtab_and_line cursal =
get_current_source_symtab_and_line ();
default_symtab = cursal.symtab;
default_line = cursal.line;
}
if (**argptr == '*')
{
(*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;
}
is_quoted = (**argptr
&& strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL);
has_parens = ((pp = strchr (*argptr, '(')) != NULL
&& (pp = strrchr (pp, ')')) != NULL);
ii = find_toplevel_char (*argptr, ',');
has_comma = (ii != 0);
if (has_comma)
{
*ii = '\0';
}
s = NULL;
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 (!*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 = ',';
if (allow_objc_selectors_flag && !has_comma)
{
char *copy = NULL;
struct block *block;
if (s)
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
else
block = get_selected_block (0);
copy = find_imps (s, 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 (s, block, *argptr, sym_arr, &i1, &i2);
*argptr = copy;
}
if (i1 == 1)
{
extern int info_verbose;
if (i2 > 0)
{
sym = sym_arr[0];
}
else
{
sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
if ((sym != NULL) && strcmp (SYMBOL_NAME (sym_arr[0]), SYMBOL_NAME (sym)) != 0)
{
warning ("debugging symbol \"%s\" does not match selector; ignoring", SYMBOL_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_SOURCE_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 (is_quoted)
{
if (!**argptr
|| strchr (get_gdb_completer_quote_characters (), **argptr) == NULL)
;
else
*argptr = *argptr + 1;
}
return values;
}
if (i1 > 1)
{
return decode_line_2 (sym_arr, i1, i2, funfirstline, canonical);
}
}
if ((p[0] == ':' || p[0] == '.') && !has_parens)
{
if (is_quoted)
*argptr = *argptr + 1;
if (p[0] == '.' || p[1] == ':')
{
char *saved_arg2 = *argptr;
char *temp_end;
if (p[0] == ':'
&& ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
saved_arg2 += 2;
p2 = p;
while (1)
{
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;
sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
(struct symtab **) NULL);
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, gdb_completer_word_break_characters);
*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;
sym = 0;
i1 = 0;
sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
* sizeof (struct symbol *));
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_NAMESPACE, (int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
i1++;
}
}
else
i1 = find_methods (t, copy, 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)
{
return decode_line_2 (sym_arr, i1, i1, funfirstline, 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 (tmp[0] == '~')
cplusplus_error (saved_arg,
"the class `%s' does not have destructor defined\n",
SYMBOL_SOURCE_NAME (sym_class));
else
cplusplus_error (saved_arg,
"the class %s does not have any method named %s\n",
SYMBOL_SOURCE_NAME (sym_class), tmp);
}
}
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;
}
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_NAMESPACE, 0, &sym_symtab);
s = (struct symtab *) 0;
if (sym)
goto symbol_found;
cplusplus_error (saved_arg,
"Can't find member of namespace, class, struct, or union named \"%s\"\n",
copy);
}
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;
s = lookup_symtab (copy);
if (s == 0)
{
if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
error ("No source file named %s.", copy);
}
p = p1 + 1;
while (*p == ' ' || *p == '\t')
p++;
*argptr = p;
}
#if 0
else
{
copy = (char *) alloca (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = '\000';
sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
if (sym)
{
*argptr = (*p == '\'') ? p + 1 : p;
s = (struct symtab *) 0;
goto symbol_found;
}
}
#endif
q = *argptr;
if (*q == '-' || *q == '+')
q++;
while (*q >= '0' && *q <= '9')
q++;
if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
{
enum sign
{
none, plus, minus
}
sign = none;
int need_canonical = (s == 0) ? 1 : 0;
if (s == 0 && default_symtab == 0)
{
struct symtab_and_line cursal;
set_default_source_symtab_and_line ();
cursal = get_current_source_symtab_and_line ();
default_symtab = cursal.symtab;
default_line = cursal.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 (s == 0)
val.line = default_line + val.line;
break;
case minus:
if (q == *argptr)
val.line = 15;
if (s == 0)
val.line = default_line - val.line;
else
val.line = 1;
break;
case none:
break;
}
while (*q == ' ' || *q == '\t')
q++;
*argptr = q;
if (s == 0)
s = default_symtab;
val.symtab = find_line_symtab (s, val.line, NULL, NULL);
if (val.symtab == 0)
val.symtab = s;
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;
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;
}
if (**argptr == '$')
{
p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1),
gdb_completer_word_break_characters);
}
else if (is_quoted)
{
p = skip_quoted (*argptr, "");
if (p[-1] != '\'')
error ("Unmatched single quote.");
}
else if (has_parens)
{
p = pp + 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 == '$')
{
struct value *valx;
int index = 0;
int need_canonical = 0;
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_NAMESPACE, 0, &sym_symtab);
s = (struct symtab *) 0;
need_canonical = 1;
if (sym)
goto symbol_found;
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
if (msymbol)
goto minimal_symbol_found;
need_canonical = (s == 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.");
}
val.symtab = s ? s : 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;
}
sym = lookup_symbol (copy,
(s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
: get_selected_block (0)),
VAR_NAMESPACE, 0, &sym_symtab);
symbol_found:
if (sym != NULL)
{
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 (s == 0)
{
struct blockvector *bv = BLOCKVECTOR (sym_symtab);
struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
if (lookup_block_symbol (b, copy, NULL, VAR_NAMESPACE) != 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);
}
}
minimal_symbol_found:
if (s == NULL)
{
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
if (msymbol != NULL)
{
values.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
(struct sec *) 0, 0);
values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
if (funfirstline)
{
values.sals[0].pc += FUNCTION_START_OFFSET;
values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
}
values.nelts = 1;
return values;
}
}
if (!have_full_symbols () &&
!have_partial_symbols () && !have_minimal_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
if (metrowerks_ignore_breakpoint_errors_flag)
{
values.sals = NULL;
return values;
}
if (s == NULL)
error ("Function \"%s\" not defined.", copy);
else
error ("Function \"%s\" not defined in file %s.", copy, s->filename);
return values;
}
struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
int default_line, char ***canonical)
{
struct symtabs_and_lines sal;
char *ii = NULL;
int has_if = 0;
if ((ii = strstr (*argptr, " if ")) != NULL ||
(ii = strstr (*argptr, "\tif ")) != NULL ||
(ii = strstr (*argptr, " if\t")) != NULL ||
(ii = strstr (*argptr, "\tif\t")) != NULL ||
(ii = strstr (*argptr, " if(")) != NULL ||
(ii = strstr (*argptr, "\tif( ")) != NULL)
has_if = 1;
if (has_if)
*ii = '\0';
sal = decode_line_1a (argptr, funfirstline, default_symtab, default_line, canonical);
if (has_if)
*ii = ' ';
return sal;
}