#include "breakpoint.h"
#include "demangle.h"
-/* These are just for containing_function_bounds. It might be better
- to move containing_function_bounds to blockframe.c or thereabouts. */
-#include "bfd.h"
-#include "symfile.h"
-#include "objfiles.h"
-
extern int asm_demangle; /* Whether to demangle syms in asm printouts */
extern int addressprint; /* Whether to print hex addresses in HLL " */
static void
disassemble_command PARAMS ((char *, int));
-static int
-containing_function_bounds PARAMS ((CORE_ADDR, CORE_ADDR *, CORE_ADDR *));
-
static void
printf_command PARAMS ((char *, int));
vprintf (string, args_to_vprintf);
}
\f
-/* Helper function for asdump_command. Finds the bounds of a function
- for a specified section of text. PC is an address within the
- function which you want bounds for; *LOW and *HIGH are set to the
- beginning (inclusive) and end (exclusive) of the function. This
- function returns 1 on success and 0 on failure. */
-
-static int
-containing_function_bounds (pc, low, high)
- CORE_ADDR pc, *low, *high;
-{
- CORE_ADDR scan;
- CORE_ADDR limit;
- struct obj_section *sec;
-
- if (!find_pc_partial_function (pc, 0, low))
- return 0;
-
- sec = find_pc_section (pc);
- if (sec == NULL)
- return 0;
- limit = sec->endaddr;
-
- scan = *low;
- while (scan < limit)
- {
- ++scan;
- if (!find_pc_partial_function (scan, 0, high))
- return 0;
- if (*low != *high)
- return 1;
- }
- *high = limit;
- return 1;
-}
-
/* Dump a specified section of assembly code. With no command line
arguments, this command will dump the assembly code for the
function surrounding the pc value in the selected frame. With one
int from_tty;
{
CORE_ADDR low, high;
+ char *name;
CORE_ADDR pc;
char *space_index;
+ name = NULL;
if (!arg)
{
if (!selected_frame)
error ("No frame selected.\n");
pc = get_frame_pc (selected_frame);
- if (!containing_function_bounds (pc, &low, &high))
- error ("No function contains pc specified by selected frame.\n");
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains program counter for selected frame.\n");
}
else if (!(space_index = (char *) strchr (arg, ' ')))
{
/* One argument. */
pc = parse_and_eval_address (arg);
- if (!containing_function_bounds (pc, &low, &high))
- error ("No function contains specified pc.\n");
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains specified address.\n");
}
else
{
}
printf_filtered ("Dump of assembler code ");
- if (!space_index)
+ if (name != NULL)
{
- char *name;
- find_pc_partial_function (pc, &name, 0);
printf_filtered ("for function %s:\n", name);
}
else
/* Unless it's a variable, check existence. */
if (name[0] != '$') {
+ /* These are warnings, not errors, since we don't want a
+ non-existent directory in a .gdbinit file to stop processing
+ of the .gdbinit file.
+
+ Whether they get added to the path is more debatable. Current
+ answer is yes, in case the user wants to go make the directory
+ or whatever. If the directory continues to not exist/not be
+ a directory/etc, then having them in the path should be
+ harmless. */
if (stat (name, &st) < 0)
- perror_with_name (name);
- if ((st.st_mode & S_IFMT) != S_IFDIR)
- error ("%s is not a directory.", name);
+ {
+ int save_errno = errno;
+ fprintf (stderr, "Warning: ");
+ print_sys_errmsg (name, save_errno);
+ }
+ else if ((st.st_mode & S_IFMT) != S_IFDIR)
+ warning ("%s is not a directory.", name);
}
append:
get_filename_and_charpos (s, (char **)NULL);
if (s->fullname == 0)
return 0;
- if (line >= s->nlines)
- return 0;
+ if (line > s->nlines)
+ /* Don't index off the end of the line_charpos array. */
+ return 0;
printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname,
line, s->line_charpos[line - 1],
mid_statement ? "middle" : "beg",
&& find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
{
if (start_pc == end_pc)
- printf_filtered ("Line %d of \"%s\" is at pc %s but contains no code.\n",
- sal.line, sal.symtab->filename, local_hex_string(start_pc));
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" is at address ");
+ print_address (start_pc, stdout);
+ wrap_here (" ");
+ printf_filtered (" but contains no code.\n");
+ }
else
{
- printf_filtered ("Line %d of \"%s\" starts at pc %s",
- sal.line, sal.symtab->filename,
- local_hex_string(start_pc));
- printf_filtered (" and ends at %s.\n",
- local_hex_string(end_pc));
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" starts at address ");
+ print_address (start_pc, stdout);
+ wrap_here (" ");
+ printf_filtered (" and ends at ");
+ print_address (end_pc, stdout);
+ printf_filtered (".\n");
}
+
/* x/i should display this line's code. */
set_next_address (start_pc);
+
/* Repeating "info line" should do the following line. */
last_line_listed = sal.line + 1;
void
_initialize_source ()
{
+ struct cmd_list_element *c;
current_source_symtab = 0;
init_source_path ();
- add_com ("directory", class_files, directory_command,
+ c = add_cmd ("directory", class_files, directory_command,
"Add directory DIR to beginning of search path for source files.\n\
Forget cached info on source file locations and line positions.\n\
DIR can also be $cwd for the current working directory, or $cdir for the\n\
directory in which the source file was compiled into object code.\n\
-With no argument, reset the search path to $cdir:$cwd, the default.");
+With no argument, reset the search path to $cdir:$cwd, the default.",
+ &cmdlist);
+ c->completer = filename_completer;
add_cmd ("directories", no_class, show_directories,
"Current search path for finding source files.\n\
find_methods PARAMS ((struct type *, char *, struct symbol **));
static void
-completion_list_add_name PARAMS ((char *, char *, int));
+completion_list_add_name PARAMS ((char *, char *, int, char *, char *));
static struct symtabs_and_lines
decode_line_2 PARAMS ((struct symbol *[], int, int));
}
}
- /* Now scan forward until we run out of symbols, find one whose name is
- greater than NAME, or find one we want. If there is more than one
- symbol with the right name and namespace, we return the first one.
- dbxread.c is careful to make sure that if one is a register then it
- comes first. */
+ /* Now scan forward until we run out of symbols, find one whose
+ name is greater than NAME, or find one we want. If there is
+ more than one symbol with the right name and namespace, we
+ return the first one; I believe it is now impossible for us
+ to encounter two symbols with the same name and namespace
+ here, because blocks containing argument symbols are no
+ longer sorted. */
top = BLOCK_NSYMS (block);
while (bot < top)
if (SYMBOL_CLASS (sym) != LOC_ARG &&
SYMBOL_CLASS (sym) != LOC_LOCAL_ARG &&
SYMBOL_CLASS (sym) != LOC_REF_ARG &&
- SYMBOL_CLASS (sym) != LOC_REGPARM)
+ SYMBOL_CLASS (sym) != LOC_REGPARM &&
+ SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR)
{
break;
}
{
warning ("no mangling for \"%s\"", tmp);
cplusplus_hint (saved_arg);
- return_to_top_level ();
+ return_to_top_level (RETURN_ERROR);
}
copy = (char*) alloca (3 + strlen(opname));
sprintf (copy, "__%s", opname);
warning ("the class %s does not have any method named %s",
SYMBOL_SOURCE_NAME(sym_class), tmp);
cplusplus_hint (saved_arg);
- return_to_top_level ();
+ return_to_top_level (RETURN_ERROR);
}
}
else
warning ("can't find class, struct, or union named \"%s\"",
copy);
cplusplus_hint (saved_arg);
- return_to_top_level ();
+ return_to_top_level (RETURN_ERROR);
}
}
/* end of C++ */
/* Convex: no need to suppress code on first line, if any */
val.pc = pc;
#else
- /* If SKIP_PROLOGUE left us in mid-line, and the next line is still
- part of the same function:
- advance to next line,
- recalculate its line number (might not be N+1). */
- if (val.pc != pc && val.end &&
- lookup_minimal_symbol_by_pc (pc) == lookup_minimal_symbol_by_pc (val.end)) {
- pc = val.end; /* First pc of next line */
- val = find_pc_line (pc, 0);
- }
+ /* Check if SKIP_PROLOGUE left us in mid-line, and the next
+ line is still part of the same function. */
+ if (val.pc != pc
+ && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= val.end
+ && val.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+ {
+ /* First pc of next line */
+ pc = val.end;
+ /* Recalculate the line number (might not be N+1). */
+ val = find_pc_line (pc, 0);
+ }
val.pc = pc;
#endif
values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
else
/* This can happen if it is compiled with a compiler which doesn't
put out line numbers for variables. */
+ /* FIXME: Shouldn't we just set .line and .symtab to zero and
+ return? For example, "info line foo" could print the address. */
error ("Line number not known for symbol \"%s\"", copy);
}
static int return_val_index;
static char **return_val;
-#define COMPLETION_LIST_ADD_SYMBOL(symbol, text, len) \
+#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
do { \
- completion_list_add_name (SYMBOL_NAME (symbol), text, len); \
- if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
- completion_list_add_name (SYMBOL_DEMANGLED_NAME (symbol), text, len); \
+ completion_list_add_name (SYMBOL_NAME (symbol), (sym_text), (len), \
+ (text), (word)); \
+ if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
+ completion_list_add_name \
+ (SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \
} while (0)
/* Test to see if the symbol specified by SYMNAME (which is already
- demangled for C++ symbols) matches TEXT in the first TEXT_LEN
+ demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
characters. If so, add it to the current completion list. */
static void
-completion_list_add_name (symname, text, text_len)
+completion_list_add_name (symname, sym_text, sym_text_len, text, word)
char *symname;
+ char *sym_text;
+ int sym_text_len;
char *text;
- int text_len;
+ char *word;
{
int newsize;
int i;
/* clip symbols that cannot match */
- if (strncmp (symname, text, text_len) != 0)
+ if (strncmp (symname, sym_text, sym_text_len) != 0)
{
return;
}
/* We have a match for a completion, so add SYMNAME to the current list
of matches. Note that the name is moved to freshly malloc'd space. */
- symname = savestring (symname, strlen (symname));
- if (return_val_index + 3 > return_val_size)
- {
- newsize = (return_val_size *= 2) * sizeof (char *);
- return_val = (char **) xrealloc ((char *) return_val, newsize);
- }
- return_val[return_val_index++] = symname;
- return_val[return_val_index] = NULL;
+ {
+ char *new;
+ if (word == sym_text)
+ {
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname);
+ }
+ else if (word > sym_text)
+ {
+ /* Return some portion of symname. */
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname + (word - sym_text));
+ }
+ else
+ {
+ /* Return some of SYM_TEXT plus symname. */
+ new = xmalloc (strlen (symname) + (sym_text - word) + 5);
+ strncpy (new, word, sym_text - word);
+ new[sym_text - word] = '\0';
+ strcat (new, symname);
+ }
+
+ if (return_val_index + 3 > return_val_size)
+ {
+ newsize = (return_val_size *= 2) * sizeof (char *);
+ return_val = (char **) xrealloc ((char *) return_val, newsize);
+ }
+ return_val[return_val_index++] = new;
+ return_val[return_val_index] = NULL;
+ }
}
/* Return a NULL terminated array of all symbols (regardless of class) which
I'm not going to worry about this; hopefully there won't be that many. */
char **
-make_symbol_completion_list (text)
- char *text;
+make_symbol_completion_list (text, word)
+ char *text;
+ char *word;
{
register struct symbol *sym;
register struct symtab *s;
register struct objfile *objfile;
register struct block *b, *surrounding_static_block = 0;
register int i, j;
- int text_len;
struct partial_symbol *psym;
+ /* The symbol we are completing on. Points in same buffer as text. */
+ char *sym_text;
+ /* Length of sym_text. */
+ int sym_text_len;
+
+ /* Now look for the symbol we are supposed to complete on.
+ FIXME: This should be language-specific. */
+ {
+ char *p;
+ char quote_found;
+ char *quote_pos;
+
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ return NULL;
+ else
+ {
+ /* It is not a quoted string. Break it based on the characters
+ which are in symbols. */
+ while (p > text)
+ {
+ if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+ --p;
+ else
+ break;
+ }
+ sym_text = p;
+ }
+ }
+
+ sym_text_len = strlen (sym_text);
- text_len = strlen (text);
return_val_size = 100;
return_val_index = 0;
return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
return_val[0] = NULL;
/* Look through the partial symtabs for all symbols which begin
- by matching TEXT. Add each one that you find to the list. */
+ by matching SYM_TEXT. Add each one that you find to the list. */
ALL_PSYMTABS (objfile, ps)
{
{
/* If interrupted, then quit. */
QUIT;
- COMPLETION_LIST_ADD_SYMBOL (psym, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (psym, sym_text, sym_text_len, text, word);
}
for (psym = objfile->static_psymbols.list + ps->statics_offset;
psym++)
{
QUIT;
- COMPLETION_LIST_ADD_SYMBOL (psym, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (psym, sym_text, sym_text_len, text, word);
}
}
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- COMPLETION_LIST_ADD_SYMBOL (msymbol, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
}
/* Search upwards from currently selected frame (so that we can
for (i = 0; i < BLOCK_NSYMS (b); i++)
{
sym = BLOCK_SYM (b, i);
- COMPLETION_LIST_ADD_SYMBOL (sym, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
struct type *t = SYMBOL_TYPE (sym);
if (TYPE_FIELD_NAME (t, j))
{
completion_list_add_name (TYPE_FIELD_NAME (t, j),
- text, text_len);
+ sym_text, sym_text_len, text, word);
}
}
}
for (i = 0; i < BLOCK_NSYMS (b); i++)
{
sym = BLOCK_SYM (b, i);
- COMPLETION_LIST_ADD_SYMBOL (sym, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
for (i = 0; i < BLOCK_NSYMS (b); i++)
{
sym = BLOCK_SYM (b, i);
- COMPLETION_LIST_ADD_SYMBOL (sym, text, text_len);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}