/* Print and select stack frames for GDB, the GNU debugger.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+ Foundation, Inc.
This file is part of GDB.
#include "demangle.h"
#include "inferior.h"
#include "annotate.h"
-#ifdef UI_OUT
#include "ui-out.h"
-#endif
/* Prototypes for exported functions. */
static void frame_info (char *, int);
extern int addressprint; /* Print addresses, or stay symbolic only? */
-extern int info_verbose; /* Verbosity of symbol reading msgs */
extern int lines_to_list; /* # of lines "list" command shows by default */
/* The "selected" stack frame is used by default for local and arg access.
0 for innermost, 1 for its caller, ...
or -1 for frame specified by address with no defined level. */
-int selected_frame_level;
+/* FIXME: cagney/2002-04-21: The variable `selected_frame_level' is
+ deprecated. It will dissapear `real soon now'. */
+
+int selected_frame_level; /* DEPRECATED */
+
+/* Level of the selected frame: 0 for innermost, 1 for its caller, ...
+ or -1 for NULL frame. */
+
+int
+frame_relative_level (struct frame_info *fi)
+{
+ if (fi == NULL)
+ return -1;
+ else
+ return fi->level;
+}
/* Zero means do things normally; we are interacting directly with the
user. One means print the full filename and linenumber when a
fi->pc);
if (!done)
{
- if (addressprint && mid_statement)
+ if (print_frame_info_listing_hook)
{
-#ifdef UI_OUT
- ui_out_field_core_addr (uiout, "addr", fi->pc);
- ui_out_text (uiout, "\t");
-#else
- print_address_numeric (fi->pc, 1, gdb_stdout);
- printf_filtered ("\t");
-#endif
+ print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
+ current_source_symtab = sal.symtab;
}
- if (print_frame_info_listing_hook)
- print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
else
- print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+ {
+ /* We used to do this earlier, but that is clearly
+ wrong. This function is used by many different
+ parts of gdb, including normal_stop in infrun.c,
+ which uses this to print out the current PC
+ when we stepi/nexti into the middle of a source
+ line. Only the command line really wants this
+ behavior. Other UIs probably would like the
+ ability to decide for themselves if it is desired. */
+ if (addressprint && mid_statement)
+ {
+ ui_out_field_core_addr (uiout, "addr", fi->pc);
+ ui_out_text (uiout, "\t");
+ }
+
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+ }
}
current_source_line = max (sal.line - lines_to_list / 2, 1);
}
struct symbol *func;
register char *funname = 0;
enum language funlang = language_unknown;
-#ifdef UI_OUT
struct ui_stream *stb;
struct cleanup *old_chain;
struct cleanup *list_chain;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
-#endif /* UI_OUT */
func = find_pc_function (fi->pc);
if (func)
annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
-#ifdef UI_OUT
list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
-#endif
if (level >= 0)
{
-#ifdef UI_OUT
ui_out_text (uiout, "#");
ui_out_field_fmt (uiout, "level", "%-2d", level);
ui_out_spaces (uiout, 1);
-#else
- printf_filtered ("#%-2d ", level);
-#endif
}
if (addressprint)
if (fi->pc != sal.pc || !sal.symtab || source == LOC_AND_ADDRESS)
{
annotate_frame_address ();
-#ifdef UI_OUT
ui_out_field_core_addr (uiout, "addr", fi->pc);
annotate_frame_address_end ();
ui_out_text (uiout, " in ");
-#else
- print_address_numeric (fi->pc, 1, gdb_stdout);
- annotate_frame_address_end ();
- printf_filtered (" in ");
-#endif
}
annotate_frame_function_name ();
-#ifdef UI_OUT
fprintf_symbol_filtered (stb->stream, funname ? funname : "??", funlang,
DMGL_ANSI);
ui_out_field_stream (uiout, "func", stb);
ui_out_wrap_hint (uiout, " ");
-#else
- fprintf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang,
- DMGL_ANSI);
- wrap_here (" ");
-#endif
annotate_frame_args ();
-#ifdef UI_OUT
ui_out_text (uiout, " (");
-#else
- fputs_filtered (" (", gdb_stdout);
-#endif
if (args)
{
struct print_args_args args;
-#ifdef UI_OUT
struct cleanup *args_list_chain;
-#endif
args.fi = fi;
args.func = func;
args.stream = gdb_stdout;
-#ifdef UI_OUT
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
catch_errors (print_args_stub, &args, "", RETURN_MASK_ALL);
/* FIXME: args must be a list. If one argument is a string it will
have " that will not be properly escaped. */
/* Invoke ui_out_tuple_end. */
do_cleanups (args_list_chain);
-#else
- catch_errors (print_args_stub, &args, "", RETURN_MASK_ALL);
-#endif
QUIT;
}
-#ifdef UI_OUT
ui_out_text (uiout, ")");
-#else
- printf_filtered (")");
-#endif
if (sal.symtab && sal.symtab->filename)
{
annotate_frame_source_begin ();
-#ifdef UI_OUT
ui_out_wrap_hint (uiout, " ");
ui_out_text (uiout, " at ");
annotate_frame_source_file ();
ui_out_text (uiout, ":");
annotate_frame_source_line ();
ui_out_field_int (uiout, "line", sal.line);
-#else
- wrap_here (" ");
- printf_filtered (" at ");
- annotate_frame_source_file ();
- printf_filtered ("%s", sal.symtab->filename);
- annotate_frame_source_file_end ();
- printf_filtered (":");
- annotate_frame_source_line ();
- printf_filtered ("%d", sal.line);
-#endif
annotate_frame_source_end ();
}
if (lib)
{
annotate_frame_where ();
-#ifdef UI_OUT
ui_out_wrap_hint (uiout, " ");
ui_out_text (uiout, " from ");
ui_out_field_string (uiout, "from", lib);
-#else
- wrap_here (" ");
- printf_filtered (" from %s", lib);
-#endif
}
}
#endif /* PC_SOLIB */
-#ifdef UI_OUT
/* do_cleanups will call ui_out_tuple_end() for us. */
do_cleanups (list_chain);
ui_out_text (uiout, "\n");
do_cleanups (old_chain);
-#else
- printf_filtered ("\n");
-#endif
}
\f
addr_string = savestring (frame_exp, p - frame_exp);
{
- value_ptr vp;
+ struct value *vp;
tmp_cleanup = make_cleanup (xfree, addr_string);
/* NOTE: we call parse_and_eval and then both
- value_as_long and value_as_pointer rather than calling
+ value_as_long and value_as_address rather than calling
parse_and_eval_long and parse_and_eval_address because
of the issue of potential side effects from evaluating
the expression. */
if (numargs == 0)
level = value_as_long (vp);
- args[numargs++] = value_as_pointer (vp);
+ args[numargs++] = value_as_address (vp);
do_cleanups (tmp_cleanup);
}
really should be used instead of spaces to delimit; using spaces
normally works in an expression). */
#ifdef SETUP_ARBITRARY_FRAME
- error ("No frame %d", args[0]);
+ error ("No frame %s", paddr_d (args[0]));
#endif
/* If (s)he specifies the frame with an address, he deserves what
}
calling_frame_info = get_prev_frame (fi);
- if (!addr_exp && selected_frame_level >= 0)
+ if (!addr_exp && frame_relative_level (selected_frame) >= 0)
{
- printf_filtered ("Stack level %d, frame at ", selected_frame_level);
+ printf_filtered ("Stack level %d, frame at ",
+ frame_relative_level (selected_frame));
print_address_numeric (fi->frame, 1, gdb_stdout);
printf_filtered (":\n");
}
print_frame_local_vars (register struct frame_info *fi, register int num_tabs,
register struct ui_file *stream)
{
- register struct block *block = get_frame_block (fi);
+ register struct block *block = get_frame_block (fi, 0);
register int values_printed = 0;
if (block == 0)
register struct ui_file *stream)
{
register struct blockvector *bl;
- register struct block *block = get_frame_block (fi);
+ register struct block *block = get_frame_block (fi, 0);
register int values_printed = 0;
int index, have_default = 0;
char *blocks_printed;
register struct symtab *s;
selected_frame = fi;
- selected_frame_level = level;
+ /* FIXME: cagney/2002-04-21: The variable `selected_frame_level' is
+ deprecated. It will dissapear `real soon now'. */
+ selected_frame_level = level; /* DEPRECATED */
+ /* FIXME: cagney/2002-04-05: It can't be this easy (and looking at
+ the increasingly complex list of checkes, it wasn't)! GDB is
+ dragging around, and constantly updating, the global variable
+ selected_frame_level. Surely all that was needed was for the
+ level to be computed direct from the frame (by counting back to
+ the inner-most frame) or, as has been done here using a cached
+ value. For moment, check that the expected and the actual level
+ are consistent. If, after a few weeks, no one reports that this
+ assertion has failed, the global selected_frame_level and many
+ many parameters can all be deleted. */
+ if (fi == NULL && level == -1)
+ /* Ok. The target is clearing the selected frame as part of a
+ cache flush. */
+ ;
+ else if (fi != NULL && fi->level == level)
+ /* Ok. What you would expect. Level is redundant. */
+ ;
+ else if (fi != NULL && level == -1)
+ /* Ok. See breakpoint.c. The watchpoint code changes the
+ selected frame to the frame that contains the watchpoint and
+ then, later changes it back to the old value. The -1 is used
+ as a marker so that the watchpoint code can easily detect that
+ things are not what they should be. Why the watchpoint code
+ can't mindlessly save/restore the selected frame I don't know,
+ hopefully it can be simplified that way. Hopefully the global
+ selected_frame can be replaced by a frame parameter, making
+ still more simplification possible. */
+ ;
+ else
+ internal_error (__FILE__, __LINE__,
+ "Conflicting frame levels fi->level=%d, level=%d",
+ (fi ? fi->level : -1),
+ level);
if (selected_frame_level_changed_hook)
selected_frame_level_changed_hook (level);
record_selected_frame (CORE_ADDR *frameaddrp, int *levelp)
{
*frameaddrp = selected_frame ? selected_frame->frame : 0;
- *levelp = selected_frame_level;
+ *levelp = frame_relative_level (selected_frame);
}
/* Return the symbol-block in which the selected frame is executing.
- Can return zero under various legitimate circumstances. */
+ Can return zero under various legitimate circumstances.
+
+ If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the relevant
+ code address within the block returned. We use this to decide
+ which macros are in scope. */
struct block *
-get_selected_block (void)
+get_selected_block (CORE_ADDR *addr_in_block)
{
if (!target_has_stack)
return 0;
if (!selected_frame)
- return get_current_block ();
- return get_frame_block (selected_frame);
+ return get_current_block (addr_in_block);
+ return get_frame_block (selected_frame, addr_in_block);
}
/* Find a frame a certain number of levels away from FRAME.
frame expressions. */
/* ARGSUSED */
-#ifdef UI_OUT
void
select_frame_command_wrapper (char *level_exp, int from_tty)
{
select_frame_command (level_exp, from_tty);
}
-#endif
+
static void
select_frame_command (char *level_exp, int from_tty)
{
frame_command (char *level_exp, int from_tty)
{
select_frame_command (level_exp, from_tty);
- show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+ show_and_print_stack_frame (selected_frame,
+ frame_relative_level (selected_frame), 1);
}
/* The XDB Compatibility command to print the current frame. */
{
if (target_has_stack == 0 || selected_frame == 0)
error ("No stack.");
- print_only_stack_frame (selected_frame, selected_frame_level, 1);
+ print_only_stack_frame (selected_frame,
+ frame_relative_level (selected_frame), 1);
}
/* Select the frame up one or COUNT stack levels
fi = find_relative_frame (selected_frame, &count1);
if (count1 != 0 && count_exp == 0)
error ("Initial frame selected; you cannot go up.");
- select_frame (fi, selected_frame_level + count - count1);
+ select_frame (fi, frame_relative_level (selected_frame) + count - count1);
}
static void
up_command (char *count_exp, int from_tty)
{
up_silently_base (count_exp);
- show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+ show_and_print_stack_frame (selected_frame,
+ frame_relative_level (selected_frame), 1);
}
/* Select the frame down one or COUNT stack levels
error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
}
- select_frame (frame, selected_frame_level + count - count1);
+ select_frame (frame, frame_relative_level (selected_frame) + count - count1);
}
/* ARGSUSED */
down_command (char *count_exp, int from_tty)
{
down_silently_base (count_exp);
- show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+ show_and_print_stack_frame (selected_frame,
+ frame_relative_level (selected_frame), 1);
}
\f
-#ifdef UI_OUT
void
return_command_wrapper (char *retval_exp, int from_tty)
{
return_command (retval_exp, from_tty);
}
-#endif
+
static void
return_command (char *retval_exp, int from_tty)
{
CORE_ADDR selected_frame_addr;
CORE_ADDR selected_frame_pc;
struct frame_info *frame;
- value_ptr return_value = NULL;
+ struct value *return_value = NULL;
if (selected_frame == NULL)
error ("No selected frame.");