old-cross-binutils/gdb/tui/tui-winsource.c
Tom Tromey f8eba3c616 the "ambiguous linespec" series
gdb
2011-12-06  Joel Brobecker  <brobecker@acacore.com>

        * language.h (struct language_defn): Add new component
        la_symbol_name_compare.
        * symfile.h (struct quick_symbol_functions): Update the profile
        of parameter "name_matcher" for the expand_symtabs_matching
        method.  Update the documentation accordingly.
        * ada-lang.h (ada_name_for_lookup): Add declaration.
        * ada-lang.c (ada_name_for_lookup): New function, extracted out
        from ada_iterate_over_symbols.
        (ada_iterate_over_symbols): Do not encode symbol name anymore.
        (ada_expand_partial_symbol_name): Adjust profile.
        (ada_language_defn): Add value for la_symbol_name_compare field.
        * linespec.c: #include "ada-lang.h".
        (iterate_name_matcher): Add language parameter. Replace call
        to strcmp_iw by call to language->la_symbol_name_compare.
        (decode_variable): Encode COPY if current language is Ada.
        * dwarf2read.c (dw2_expand_symtabs_matching): Adjust profile
        of name_matcher parameter.  Adjust call to name_matcher.
        * psymtab.c (expand_symtabs_matching_via_partial): Likewise.
        (expand_partial_symbol_names): Update profile of parameter "fun".
        * psymtab.h (expand_partial_symbol_names): Update profile of
        parameter "fun".
        * symtab.c (demangle_for_lookup): Update function documentation.
        (search_symbols_name_matches): Add language parameter.
        (expand_partial_symbol_name): Likewise.
        * c-lang.c (c_language_defn, cplus_language_defn)
        (asm_language_defn, minimal_language_defn): Add value for
        la_symbol_name_compare field.
        * d-lang.c (d_language_defn): Likewise.
        * f-lang.c (f_language_defn): Ditto.
        * jv-lang.c (java_language_defn): Ditto.
        * m2-lang.c (m2_language_defn): Ditto.
        * objc-lang.c (objc_language_defn): Ditto.
        * opencl-lang.c (opencl_language_defn): Ditto.
        * p-lang.c (pascal_language_defn): Ditto.
        * language.c (unknown_language_defn, auto_language_defn)
        (local_language_defn): Ditto.

2011-12-06  Tom Tromey  <tromey@redhat.com>

	* linespec.c (iterate_over_all_matching_symtabs): Use
	LA_ITERATE_OVER_SYMBOLS.
	(lookup_prefix_sym, add_matching_symbols_to_info): Likewise.
	(find_function_symbols, decode_variable): Remove Ada special
	case.
	* language.h (struct language_defn) <la_iterate_over_symbols>: New
	field.
	(LA_ITERATE_OVER_SYMBOLS): New macro.
	* language.c (unknown_language_defn, auto_language_defn)
	(local_language_defn): Update.
	* c-lang.c (c_language_defn, cplus_language_defn)
	(asm_language_defn, minimal_language_defn): Update.
	* d-lang.c (d_language_defn): Update.
	* f-lang.c (f_language_defn): Update.
	* jv-lang.c (java_language_defn): Update.
	* m2-lang.c (m2_language_defn): Update.
	* objc-lang.c (objc_language_defn): Update.
	* opencl-lang.c (opencl_language_defn): Update.
	* p-lang.c (pascal_language_defn): Update.
	* ada-lang.c (ada_iterate_over_symbols): New function.
	(ada_language_defn): Update.

2011-12-06  Tom Tromey  <tromey@redhat.com>
	    Joel Brobecker  <brobecker@acacore.com>

	PR breakpoints/13105, PR objc/8341, PR objc/8343, PR objc/8366,
	PR objc/8535, PR breakpoints/11657, PR breakpoints/11970,
	PR breakpoints/12023, PR breakpoints/12334, PR breakpoints/12856,
	PR shlibs/8929, PR shlibs/7393:
	* python/py-type.c (compare_maybe_null_strings): Rename from
	compare_strings.
	(check_types_equal): Update.
	* utils.c (compare_strings): New function.
	* tui/tui-winsource.c (tui_update_breakpoint_info): Update for
	location changes.
	* tracepoint.c (scope_info): Update.
	(trace_find_line_command): Use DECODE_LINE_FUNFIRSTLINE.
	* symtab.h (iterate_over_minimal_symbols)
	(iterate_over_some_symtabs, iterate_over_symtabs)
	(find_pcs_for_symtab_line, iterate_over_symbols)
	(demangle_for_lookup): Declare.
	(expand_line_sal): Remove.
	* symtab.c (iterate_over_some_symtabs, iterate_over_symtabs)
	(lookup_symtab_callback): New functions.
	(lookup_symtab): Rewrite.
	(demangle_for_lookup): New function, extract from
	lookup_symbol_in_language.
	(lookup_symbol_in_language): Use it.
	(iterate_over_symbols): New function.
	(find_line_symtab): Update.
	(find_pcs_for_symtab_line): New functions.
	(find_line_common): Add 'start' argument.
	(decode_line_spec): Update.  Change argument to 'flags', change
	interpretation.
	(append_expanded_sal): Remove.
	(append_exact_match_to_sals): Remove.
	(expand_line_sal): Remove.
	* symfile.h (struct quick_symbol_functions) <lookup_symtab>:
	Remove.
	<map_symtabs_matching_filename>: New field.
	* stack.c (func_command): Only look in the current program space.
	Use DECODE_LINE_FUNFIRSTLINE.
	* source.c (line_info): Set pspace on sal.  Check program space in
	the loop.  Use DECODE_LINE_LIST_MODE.
	(select_source_symtab): Use DECODE_LINE_FUNFIRSTLINE.
	* solib-target.c: Remove DEF_VEC_I(CORE_ADDR).
	* python/python.c (gdbpy_decode_line): Update.
	* psymtab.c (partial_map_expand_apply): New function.
	(partial_map_symtabs_matching_filename): Rename from
	lookup_partial_symbol.  Update arguments.
	(lookup_symtab_via_partial_symtab): Remove.
	(psym_functions): Update.
	* objc-lang.h (parse_selector, parse_method): Don't declare.
	(find_imps): Update.
	* objc-lang.c (parse_selector, parse_method): Now static.
	(find_methods): Change arguments.  Fill in a vector of symbol
	names.
	(uniquify_strings): New function.
	(find_imps): Change arguments.
	* minsyms.c (iterate_over_minimal_symbols): New function.
	* linespec.h (enum decode_line_flags): New.
	(struct linespec_sals): New.
	(struct linespec_result) <canonical>: Remove.
	<pre_expanded, addr_string, sals>: New fields.
	(destroy_linespec_result, make_cleanup_destroy_linespec_result)
	(decode_line_full): Declare.
	(decode_line_1): Update.
	* linespec.c (struct address_entry, struct linespec_state, struct
	collect_info): New types.
	(add_sal_to_sals_basic, add_sal_to_sals, hash_address_entry)
	(eq_address_entry, maybe_add_address): New functions.
	(total_number_of_methods): Remove.
	(iterate_name_matcher, iterate_over_all_matching_symtabs): New
	functions.
	(find_methods): Change arguments.  Don't canonicalize input.
	Simplify logic.
	(add_matching_methods, add_constructors)
	(build_canonical_line_spec): Remove.
	(filter_results, convert_results_to_lsals): New functions.
	(decode_line_2): Change arguments.  Rewrite for new data
	structures.
	(decode_line_internal): Rename from decode_line_1.  Change
	arguments.  Add cleanups.  Update for new data structures.
	(linespec_state_constructor, linespec_state_destructor)
	(decode_line_full, decode_line_1): New functions.
	(decode_indirect): Change arguments.  Update.
	(locate_first_half): Use skip_spaces.
	(decode_objc): Change arguments.  Update for new data structures.
	Simplify logic.
	(decode_compound): Change arguments.  Add cleanups.  Remove
	fallback code, replace with error.
	(struct decode_compound_collector): New type.
	(collect_one_symbol): New function.
	(lookup_prefix_sym): Change arguments.  Update.
	(compare_symbol_name, add_all_symbol_names_from_pspace)
	(find_superclass_methods ): New functions.
	(find_method): Rewrite.
	(struct symtab_collector): New type.
	(add_symtabs_to_list, collect_symtabs_from_filename): New
	functions.
	(symtabs_from_filename): Change API.  Rename from
	symtab_from_filename.
	(collect_function_symbols): New function.
	(find_function_symbols): Change API.  Rename from
	find_function_symbol.  Rewrite.
	(decode_all_digits): Change arguments.  Rewrite.
	(decode_dollar): Change arguments.  Use decode_variable.
	(decode_label): Change arguments.  Rewrite.
	(collect_symbols): New function.
	(minsym_found): Change arguments.  Rewrite.
	(check_minsym, search_minsyms_for_name)
	(add_matching_symbols_to_info): New function.
	(decode_variable): Change arguments.  Iterate over all symbols.
	(symbol_found): Remove.
	(symbol_to_sal): New function.
	(init_linespec_result, destroy_linespec_result)
	(cleanup_linespec_result, make_cleanup_destroy_linespec_result):
	New functions.
	(decode_digits_list_mode, decode_digits_ordinary): New functions.
	* dwarf2read.c (dw2_map_expand_apply): New function.
	(dw2_map_symtabs_matching_filename): Rename from
	dw2_lookup_symtab.  Change arguments.
	(dwarf2_gdb_index_functions): Update.
	* dwarf2loc.c: Remove DEF_VEC_I(CORE_ADDR).
	* defs.h (compare_strings): Declare.
	* cli/cli-cmds.c (compare_strings): Move to utils.c.
	(edit_command, list_command): Use DECODE_LINE_LIST_MODE.  Call
	filter_sals.
	(compare_symtabs, filter_sals): New functions.
	* breakpoint.h (struct bp_location) <line_number, source_file>:
	New fields.
	(struct breakpoint) <line_number, source_file>: Remove.
	<filter>: New field.
	* breakpoint.c (print_breakpoint_location, init_raw_breakpoint)
	(momentary_breakpoint_from_master, add_location_to_breakpoint):
	Update for changes to locations.
	(init_breakpoint_sal): Add 'filter' argument.  Set 'filter' on
	breakpoint.
	(create_breakpoint_sal): Add 'filter' argument.
	(remove_sal, expand_line_sal_maybe): Remove.
	(create_breakpoints_sal): Remove 'sals' argument.  Handle
	pre-expanded sals and the filter.
	(parse_breakpoint_sals): Use decode_line_full.
	(check_fast_tracepoint_sals): Use get_sal_arch.
	(create_breakpoint): Create a linespec_sals.  Update.
	(break_range_command): Use decode_line_full.  Update.
	(until_break_command): Update.
	(clear_command): Update match conditions for linespec.c changes.
	Use DECODE_LINE_LIST_MODE.
	(say_where): Update for changes to locations.
	(bp_location_dtor): Free 'source_file'.
	(base_breakpoint_dtor): Free 'filter'.  Don't free 'source_file'.
	(update_static_tracepoint): Update for changes to locations.
	(update_breakpoint_locations): Disable ranged breakpoint if too
	many locations match.  Update.
	(addr_string_to_sals): Use decode_line_full.  Resolve all sal
	PCs.
	(breakpoint_re_set_default): Don't call expand_line_sal_maybe.
	(decode_line_spec_1): Update.  Change argument name to 'flags',
	change interpretation.
	* block.h (block_containing_function): Declare.
	* block.c (block_containing_function): New function.
	* skip.c (skip_function_command): Update.
	(skip_re_set): Update.
	* infcmd.c (jump_command): Use DECODE_LINE_FUNFIRSTLINE.
	* mi/mi-main.c (mi_cmd_trace_find): Use DECODE_LINE_FUNFIRSTLINE.
	* NEWS: Add entry.

2011-12-06  Tom Tromey  <tromey@redhat.com>

	* elfread.c (elf_gnu_ifunc_resolver_return_stop): Allow
	breakpoint's pspace to be NULL.
	* breakpoint.h (struct breakpoint) <pspace>: Update comment.
	* breakpoint.c (init_raw_breakpoint): Conditionally set
	breakpoint's pspace.
	(init_breakpoint_sal): Don't set breakpoint's pspace.
	(prepare_re_set_context): Conditionally switch program space.
	(addr_string_to_sals): Check executing_startup on location's
	program space.

2011-12-06  Tom Tromey  <tromey@redhat.com>

	* breakpoint.h (enum enable_state) <bp_startup_disabled>: Remove.
	* breakpoint.c (should_be_inserted): Explicitly check if program
	space is executing startup.
	(describe_other_breakpoints): Update.
	(disable_breakpoints_before_startup): Change executing_startup
	earlier.  Remove loop.
	(enable_breakpoints_after_startup): Likewise.
	(init_breakpoint_sal): Don't use bp_startup_disabled.
	(create_breakpoint): Don't use bp_startup_disabled.
	(update_global_location_list): Use should_be_inserted.
	(bkpt_re_set): Update.
gdb/testsuite
2011-12-06  Joel Brobecker  <brobecker@acacore.com>

        * gdb.ada/fullname_bp.exp: Add tests for other valid linespecs
        involving a fully qualified function name.

2011-12-06  Tom Tromey  <tromey@redhat.com>

	* gdb.ada/homonym.exp: Add three breakpoint tests.

2011-12-06  Tom Tromey  <tromey@redhat.com>

	* gdb.base/solib-weak.exp (do_test): Remove kfail.
	* gdb.trace/tracecmd.exp: Disable pending breakpoints earlier.
	* gdb.objc/objcdecode.exp: Update for output changes.
	* gdb.linespec/linespec.exp: New file.
	* gdb.linespec/lspec.cc: New file.
	* gdb.linespec/lspec.h: New file.
	* gdb.linespec/body.h: New file.
	* gdb.linespec/base/two/thefile.cc: New file.
	* gdb.linespec/base/one/thefile.cc: New file.
	* gdb.linespec/Makefile.in: New file.
	* gdb.cp/templates.exp (test_template_breakpoints): Update for
	output changes.
	* gdb.cp/re-set-overloaded.exp: Remove kfail.
	* gdb.cp/ovldbreak.exp: Update for output changes.  "all" test now
	makes one breakpoint.
	* gdb.cp/method2.exp (test_break): Update for output changes.
	* gdb.cp/mb-templates.exp: Update for output changes.
	* gdb.cp/mb-inline.exp: Update for output changes.
	* gdb.cp/mb-ctor.exp: Update for output changes.
	* gdb.cp/ovsrch.exp: Use fully-qualified names.
	* gdb.base/solib-symbol.exp: Run to main later.  Breakpoint now
	has multiple matches.
	* gdb.base/sepdebug.exp: Disable pending breakpoints.  Update for
	error message change.
	* gdb.base/list.exp (test_list_filename_and_number): Update for
	error message change.
	* gdb.base/break.exp: Disable pending breakpoints.  Update for
	output changes.
	* configure.ac: Add gdb.linespec.
	* configure: Rebuild.
	* Makefile.in (ALL_SUBDIRS): Add gdb.linespec.
gdb/doc
2011-12-06  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Set Breaks): Update for new behavior.
2011-12-06 18:54:43 +00:00

717 lines
19 KiB
C

/* TUI display source/assembly window.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008,
2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Hewlett-Packard Company.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include <ctype.h>
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
#include "value.h"
#include "source.h"
#include "objfiles.h"
#include "filenames.h"
#include "tui/tui.h"
#include "tui/tui-data.h"
#include "tui/tui-stack.h"
#include "tui/tui-win.h"
#include "tui/tui-wingeneral.h"
#include "tui/tui-winsource.h"
#include "tui/tui-source.h"
#include "tui/tui-disasm.h"
#include "gdb_string.h"
#include "gdb_curses.h"
#include "gdb_assert.h"
/* Function to display the "main" routine. */
void
tui_display_main (void)
{
if ((tui_source_windows ())->count > 0)
{
struct gdbarch *gdbarch;
CORE_ADDR addr;
tui_get_begin_asm_address (&gdbarch, &addr);
if (addr != (CORE_ADDR) 0)
{
struct symtab_and_line sal;
tui_update_source_windows_with_addr (gdbarch, addr);
sal = find_pc_line (addr, 0);
if (sal.symtab)
tui_update_locator_filename (sal.symtab->filename);
else
tui_update_locator_filename ("??");
}
}
}
/* Function to display source in the source window. This function
initializes the horizontal scroll to 0. */
void
tui_update_source_window (struct tui_win_info *win_info,
struct gdbarch *gdbarch,
struct symtab *s,
struct tui_line_or_address line_or_addr,
int noerror)
{
win_info->detail.source_info.horizontal_offset = 0;
tui_update_source_window_as_is (win_info, gdbarch, s, line_or_addr, noerror);
return;
}
/* Function to display source in the source/asm window. This function
shows the source as specified by the horizontal offset. */
void
tui_update_source_window_as_is (struct tui_win_info *win_info,
struct gdbarch *gdbarch,
struct symtab *s,
struct tui_line_or_address line_or_addr,
int noerror)
{
enum tui_status ret;
if (win_info->generic.type == SRC_WIN)
ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
else
ret = tui_set_disassem_content (gdbarch, line_or_addr.u.addr);
if (ret == TUI_FAILURE)
{
tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
tui_clear_exec_info_content (win_info);
}
else
{
tui_update_breakpoint_info (win_info, 0);
tui_show_source_content (win_info);
tui_update_exec_info (win_info);
if (win_info->generic.type == SRC_WIN)
{
struct symtab_and_line sal;
init_sal (&sal);
sal.line = line_or_addr.u.line_no +
(win_info->generic.content_size - 2);
sal.symtab = s;
sal.pspace = s->objfile->pspace;
set_current_source_symtab_and_line (&sal);
/* If the focus was in the asm win, put it in the src win if
we don't have a split layout. */
if (tui_win_with_focus () == TUI_DISASM_WIN
&& tui_current_layout () != SRC_DISASSEM_COMMAND)
tui_set_win_focus_to (TUI_SRC_WIN);
}
}
return;
}
/* Function to ensure that the source and/or disassemly windows
reflect the input address. */
void
tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
{
if (addr != 0)
{
struct symtab_and_line sal;
struct tui_line_or_address l;
switch (tui_current_layout ())
{
case DISASSEM_COMMAND:
case DISASSEM_DATA_COMMAND:
tui_show_disassem (gdbarch, addr);
break;
case SRC_DISASSEM_COMMAND:
tui_show_disassem_and_update_source (gdbarch, addr);
break;
default:
sal = find_pc_line (addr, 0);
l.loa = LOA_LINE;
l.u.line_no = sal.line;
tui_show_symtab_source (gdbarch, sal.symtab, l, FALSE);
break;
}
}
else
{
int i;
for (i = 0; i < (tui_source_windows ())->count; i++)
{
struct tui_win_info *win_info = (tui_source_windows ())->list[i];
tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
tui_clear_exec_info_content (win_info);
}
}
}
/* Function to ensure that the source and/or disassemly windows
reflect the input address. */
void
tui_update_source_windows_with_line (struct symtab *s, int line)
{
struct gdbarch *gdbarch;
CORE_ADDR pc;
struct tui_line_or_address l;
if (!s)
return;
gdbarch = get_objfile_arch (s->objfile);
switch (tui_current_layout ())
{
case DISASSEM_COMMAND:
case DISASSEM_DATA_COMMAND:
find_line_pc (s, line, &pc);
tui_update_source_windows_with_addr (gdbarch, pc);
break;
default:
l.loa = LOA_LINE;
l.u.line_no = line;
tui_show_symtab_source (gdbarch, s, l, FALSE);
if (tui_current_layout () == SRC_DISASSEM_COMMAND)
{
find_line_pc (s, line, &pc);
tui_show_disassem (gdbarch, pc);
}
break;
}
return;
}
void
tui_clear_source_content (struct tui_win_info *win_info,
int display_prompt)
{
if (win_info != NULL)
{
int i;
win_info->generic.content_in_use = FALSE;
tui_erase_source_content (win_info, display_prompt);
for (i = 0; i < win_info->generic.content_size; i++)
{
struct tui_win_element *element =
(struct tui_win_element *) win_info->generic.content[i];
element->which_element.source.has_break = FALSE;
element->which_element.source.is_exec_point = FALSE;
}
}
}
void
tui_erase_source_content (struct tui_win_info *win_info,
int display_prompt)
{
int x_pos;
int half_width = (win_info->generic.width - 2) / 2;
if (win_info->generic.handle != (WINDOW *) NULL)
{
werase (win_info->generic.handle);
tui_check_and_display_highlight_if_needed (win_info);
if (display_prompt == EMPTY_SOURCE_PROMPT)
{
char *no_src_str;
if (win_info->generic.type == SRC_WIN)
no_src_str = NO_SRC_STRING;
else
no_src_str = NO_DISASSEM_STRING;
if (strlen (no_src_str) >= half_width)
x_pos = 1;
else
x_pos = half_width - strlen (no_src_str);
mvwaddstr (win_info->generic.handle,
(win_info->generic.height / 2),
x_pos,
no_src_str);
/* elz: Added this function call to set the real contents of
the window to what is on the screen, so that later calls
to refresh, do display the correct stuff, and not the old
image. */
tui_set_source_content_nil (win_info, no_src_str);
}
tui_refresh_win (&win_info->generic);
}
}
/* Redraw the complete line of a source or disassembly window. */
static void
tui_show_source_line (struct tui_win_info *win_info, int lineno)
{
struct tui_win_element *line;
int x, y;
line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
if (line->which_element.source.is_exec_point)
wattron (win_info->generic.handle, A_STANDOUT);
mvwaddstr (win_info->generic.handle, lineno, 1,
line->which_element.source.line);
if (line->which_element.source.is_exec_point)
wattroff (win_info->generic.handle, A_STANDOUT);
/* Clear to end of line but stop before the border. */
getyx (win_info->generic.handle, y, x);
while (x + 1 < win_info->generic.width)
{
waddch (win_info->generic.handle, ' ');
getyx (win_info->generic.handle, y, x);
}
}
void
tui_show_source_content (struct tui_win_info *win_info)
{
if (win_info->generic.content_size > 0)
{
int lineno;
for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
tui_show_source_line (win_info, lineno);
}
else
tui_erase_source_content (win_info, TRUE);
tui_check_and_display_highlight_if_needed (win_info);
tui_refresh_win (&win_info->generic);
win_info->generic.content_in_use = TRUE;
}
/* Scroll the source forward or backward horizontally. */
void
tui_horizontal_source_scroll (struct tui_win_info *win_info,
enum tui_scroll_direction direction,
int num_to_scroll)
{
if (win_info->generic.content != NULL)
{
struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
int offset;
struct symtab *s = NULL;
if (win_info->generic.type == SRC_WIN)
{
struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
if (cursal.symtab == NULL)
s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
else
s = cursal.symtab;
}
if (direction == LEFT_SCROLL)
offset = win_info->detail.source_info.horizontal_offset
+ num_to_scroll;
else
{
offset = win_info->detail.source_info.horizontal_offset
- num_to_scroll;
if (offset < 0)
offset = 0;
}
win_info->detail.source_info.horizontal_offset = offset;
tui_update_source_window_as_is (win_info, gdbarch, s,
((struct tui_win_element *)
win_info->generic.content[0])->which_element.source.line_or_addr,
FALSE);
}
return;
}
/* Set or clear the has_break flag in the line whose line is
line_no. */
void
tui_set_is_exec_point_at (struct tui_line_or_address l,
struct tui_win_info *win_info)
{
int changed = 0;
int i;
tui_win_content content = (tui_win_content) win_info->generic.content;
i = 0;
while (i < win_info->generic.content_size)
{
int new_state;
struct tui_line_or_address content_loa =
content[i]->which_element.source.line_or_addr;
gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
gdb_assert (content_loa.loa == LOA_LINE
|| content_loa.loa == LOA_ADDRESS);
if (content_loa.loa == l.loa
&& ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
|| (content_loa.u.addr == l.u.addr)))
new_state = TRUE;
else
new_state = FALSE;
if (new_state != content[i]->which_element.source.is_exec_point)
{
changed++;
content[i]->which_element.source.is_exec_point = new_state;
tui_show_source_line (win_info, i + 1);
}
i++;
}
if (changed)
tui_refresh_win (&win_info->generic);
}
/* Update the execution windows to show the active breakpoints.
This is called whenever a breakpoint is inserted, removed or
has its state changed. */
void
tui_update_all_breakpoint_info (void)
{
struct tui_list *list = tui_source_windows ();
int i;
for (i = 0; i < list->count; i++)
{
struct tui_win_info *win = list->list[i];
if (tui_update_breakpoint_info (win, FALSE))
{
tui_update_exec_info (win);
}
}
}
/* Scan the source window and the breakpoints to update the has_break
information for each line.
Returns 1 if something changed and the execution window must be
refreshed. */
int
tui_update_breakpoint_info (struct tui_win_info *win,
int current_only)
{
int i;
int need_refresh = 0;
struct tui_source_info *src = &win->detail.source_info;
for (i = 0; i < win->generic.content_size; i++)
{
struct breakpoint *bp;
extern struct breakpoint *breakpoint_chain;
int mode;
struct tui_source_element *line;
line = &((struct tui_win_element *)
win->generic.content[i])->which_element.source;
if (current_only && !line->is_exec_point)
continue;
/* Scan each breakpoint to see if the current line has something to
do with it. Identify enable/disabled breakpoints as well as
those that we already hit. */
mode = 0;
for (bp = breakpoint_chain;
bp != (struct breakpoint *) NULL;
bp = bp->next)
{
struct bp_location *loc;
gdb_assert (line->line_or_addr.loa == LOA_LINE
|| line->line_or_addr.loa == LOA_ADDRESS);
for (loc = bp->loc; loc != NULL; loc = loc->next)
{
if ((win == TUI_SRC_WIN
&& loc->source_file
&& (filename_cmp (src->filename, loc->source_file) == 0)
&& line->line_or_addr.loa == LOA_LINE
&& loc->line_number == line->line_or_addr.u.line_no)
|| (win == TUI_DISASM_WIN
&& line->line_or_addr.loa == LOA_ADDRESS
&& loc->address == line->line_or_addr.u.addr))
{
if (bp->enable_state == bp_disabled)
mode |= TUI_BP_DISABLED;
else
mode |= TUI_BP_ENABLED;
if (bp->hit_count)
mode |= TUI_BP_HIT;
if (bp->loc->cond)
mode |= TUI_BP_CONDITIONAL;
if (bp->type == bp_hardware_breakpoint)
mode |= TUI_BP_HARDWARE;
}
}
}
if (line->has_break != mode)
{
line->has_break = mode;
need_refresh = 1;
}
}
return need_refresh;
}
/* Function to initialize the content of the execution info window,
based upon the input window which is either the source or
disassembly window. */
enum tui_status
tui_set_exec_info_content (struct tui_win_info *win_info)
{
enum tui_status ret = TUI_SUCCESS;
if (win_info->detail.source_info.execution_info
!= (struct tui_gen_win_info *) NULL)
{
struct tui_gen_win_info *exec_info_ptr
= win_info->detail.source_info.execution_info;
if (exec_info_ptr->content == NULL)
exec_info_ptr->content =
(void **) tui_alloc_content (win_info->generic.height,
exec_info_ptr->type);
if (exec_info_ptr->content != NULL)
{
int i;
tui_update_breakpoint_info (win_info, 1);
for (i = 0; i < win_info->generic.content_size; i++)
{
struct tui_win_element *element;
struct tui_win_element *src_element;
int mode;
element = (struct tui_win_element *) exec_info_ptr->content[i];
src_element = (struct tui_win_element *)
win_info->generic.content[i];
memset(element->which_element.simple_string, ' ',
sizeof(element->which_element.simple_string));
element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
/* Now update the exec info content based upon the state
of each line as indicated by the source content. */
mode = src_element->which_element.source.has_break;
if (mode & TUI_BP_HIT)
element->which_element.simple_string[TUI_BP_HIT_POS] =
(mode & TUI_BP_HARDWARE) ? 'H' : 'B';
else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
element->which_element.simple_string[TUI_BP_HIT_POS] =
(mode & TUI_BP_HARDWARE) ? 'h' : 'b';
if (mode & TUI_BP_ENABLED)
element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
else if (mode & TUI_BP_DISABLED)
element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
if (src_element->which_element.source.is_exec_point)
element->which_element.simple_string[TUI_EXEC_POS] = '>';
}
exec_info_ptr->content_size = win_info->generic.content_size;
}
else
ret = TUI_FAILURE;
}
return ret;
}
void
tui_show_exec_info_content (struct tui_win_info *win_info)
{
struct tui_gen_win_info *exec_info
= win_info->detail.source_info.execution_info;
int cur_line;
werase (exec_info->handle);
tui_refresh_win (exec_info);
for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
mvwaddstr (exec_info->handle,
cur_line,
0,
((struct tui_win_element *)
exec_info->content[cur_line - 1])->which_element.simple_string);
tui_refresh_win (exec_info);
exec_info->content_in_use = TRUE;
}
void
tui_erase_exec_info_content (struct tui_win_info *win_info)
{
struct tui_gen_win_info *exec_info
= win_info->detail.source_info.execution_info;
werase (exec_info->handle);
tui_refresh_win (exec_info);
}
void
tui_clear_exec_info_content (struct tui_win_info *win_info)
{
win_info->detail.source_info.execution_info->content_in_use = FALSE;
tui_erase_exec_info_content (win_info);
return;
}
/* Function to update the execution info window. */
void
tui_update_exec_info (struct tui_win_info *win_info)
{
tui_set_exec_info_content (win_info);
tui_show_exec_info_content (win_info);
}
enum tui_status
tui_alloc_source_buffer (struct tui_win_info *win_info)
{
char *src_line_buf;
int i, line_width, max_lines;
max_lines = win_info->generic.height; /* Less the highlight box. */
line_width = win_info->generic.width - 1;
/*
* Allocate the buffer for the source lines. Do this only once
* since they will be re-used for all source displays. The only
* other time this will be done is when a window's size changes.
*/
if (win_info->generic.content == NULL)
{
src_line_buf = (char *)
xmalloc ((max_lines * line_width) * sizeof (char));
if (src_line_buf == (char *) NULL)
{
fputs_unfiltered ("Unable to Allocate Memory for "
"Source or Disassembly Display.\n",
gdb_stderr);
return TUI_FAILURE;
}
/* Allocate the content list. */
if ((win_info->generic.content =
(void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
{
xfree (src_line_buf);
fputs_unfiltered ("Unable to Allocate Memory for "
"Source or Disassembly Display.\n",
gdb_stderr);
return TUI_FAILURE;
}
for (i = 0; i < max_lines; i++)
((struct tui_win_element *)
win_info->generic.content[i])->which_element.source.line =
src_line_buf + (line_width * i);
}
return TUI_SUCCESS;
}
/* Answer whether a particular line number or address is displayed
in the current source window. */
int
tui_line_is_displayed (int line,
struct tui_win_info *win_info,
int check_threshold)
{
int is_displayed = FALSE;
int i, threshold;
if (check_threshold)
threshold = SCROLL_THRESHOLD;
else
threshold = 0;
i = 0;
while (i < win_info->generic.content_size - threshold
&& !is_displayed)
{
is_displayed = (((struct tui_win_element *)
win_info->generic.content[i])->which_element.source.line_or_addr.loa
== LOA_LINE)
&& (((struct tui_win_element *)
win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
== (int) line);
i++;
}
return is_displayed;
}
/* Answer whether a particular line number or address is displayed
in the current source window. */
int
tui_addr_is_displayed (CORE_ADDR addr,
struct tui_win_info *win_info,
int check_threshold)
{
int is_displayed = FALSE;
int i, threshold;
if (check_threshold)
threshold = SCROLL_THRESHOLD;
else
threshold = 0;
i = 0;
while (i < win_info->generic.content_size - threshold
&& !is_displayed)
{
is_displayed = (((struct tui_win_element *)
win_info->generic.content[i])->which_element.source.line_or_addr.loa
== LOA_ADDRESS)
&& (((struct tui_win_element *)
win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
== addr);
i++;
}
return is_displayed;
}
/*****************************************
** STATIC LOCAL FUNCTIONS **
******************************************/