X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftui%2Ftui.c;h=99d30a55a153338e64399410da7461a11633f3ae;hb=b2efe70cf34e2f3ada8d0def69e53f27a6b71578;hp=91a26df26e8cd035b1ceee5c343dc4a6e3cd0b9c;hpb=08ef48c5ac7d25a662e76e421b5bdd6887dfc8ff;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 91a26df26e..99d30a55a1 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -1,7 +1,6 @@
/* General functions for the WDB TUI.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1998-2020 Free Software Foundation, Inc.
Contributed by Hewlett-Packard Company.
@@ -9,7 +8,7 @@
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 2 of the License, or
+ 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,
@@ -18,14 +17,13 @@
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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see . */
#include "defs.h"
#include "gdbcmd.h"
#include "tui/tui.h"
#include "tui/tui-hooks.h"
+#include "tui/tui-command.h"
#include "tui/tui-data.h"
#include "tui/tui-layout.h"
#include "tui/tui-io.h"
@@ -33,25 +31,23 @@
#include "tui/tui-stack.h"
#include "tui/tui-win.h"
#include "tui/tui-winsource.h"
-#include "tui/tui-windata.h"
+#include "tui/tui-source.h"
#include "target.h"
#include "frame.h"
#include "breakpoint.h"
#include "inferior.h"
#include "symtab.h"
#include "source.h"
+#include "terminal.h"
+#include "top.h"
-#include
-#include
#include
#include
#include
-#if 0
-#include
-#endif
#include
#include "gdb_curses.h"
+#include "interps.h"
/* This redefines CTRL if it is not already defined, so it must come
after terminal state releated include files like and
@@ -59,8 +55,8 @@
#include "readline/readline.h"
/* Tells whether the TUI is active or not. */
-int tui_active = 0;
-static int tui_finish_init = 1;
+bool tui_active = false;
+static bool tui_finish_init = true;
enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE;
@@ -77,8 +73,10 @@ static const struct tui_char_command tui_commands[] = {
{ 'd', "down" },
{ 'f', "finish" },
{ 'n', "next" },
+ { 'o', "nexti" },
{ 'r', "run" },
{ 's', "step" },
+ { 'i', "stepi" },
{ 'u', "up" },
{ 'v', "info locals" },
{ 'w', "where" },
@@ -93,15 +91,29 @@ static Keymap tui_readline_standard_keymap;
static int
tui_rl_switch_mode (int notused1, int notused2)
{
- if (tui_active)
+
+ /* Don't let exceptions escape. We're in the middle of a readline
+ callback that isn't prepared for that. */
+ try
{
- tui_disable ();
- rl_prep_terminal (0);
+ if (tui_active)
+ {
+ tui_disable ();
+ rl_prep_terminal (0);
+ }
+ else
+ {
+ /* If tui_enable throws, we'll re-prep below. */
+ rl_deprep_terminal ();
+ tui_enable ();
+ }
}
- else
+ catch (const gdb_exception &ex)
{
- rl_deprep_terminal ();
- tui_enable ();
+ exception_print (gdb_stderr, ex);
+
+ if (!tui_active)
+ rl_prep_terminal (0);
}
/* Clear the readline in case switching occurred in middle of
@@ -138,7 +150,6 @@ tui_rl_change_windows (int notused1, int notused2)
if (tui_active)
{
enum tui_layout_type new_layout;
- enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
new_layout = tui_current_layout ();
@@ -170,7 +181,7 @@ tui_rl_change_windows (int notused1, int notused2)
new_layout = SRC_COMMAND;
break;
}
- tui_set_layout (new_layout, regs_type);
+ tui_set_layout (new_layout);
}
return 0;
}
@@ -186,7 +197,6 @@ tui_rl_delete_other_windows (int notused1, int notused2)
if (tui_active)
{
enum tui_layout_type new_layout;
- enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
new_layout = tui_current_layout ();
@@ -205,7 +215,7 @@ tui_rl_delete_other_windows (int notused1, int notused2)
new_layout = DISASSEM_COMMAND;
break;
}
- tui_set_layout (new_layout, regs_type);
+ tui_set_layout (new_layout);
}
return 0;
}
@@ -224,9 +234,7 @@ tui_rl_other_window (int count, int key)
if (win_info)
{
tui_set_win_focus_to (win_info);
- if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
- tui_refresh_data_win ();
- keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
+ keypad (TUI_CMD_WIN->handle.get (), win_info != TUI_CMD_WIN);
}
return 0;
}
@@ -243,11 +251,17 @@ tui_rl_command_key (int count, int key)
{
if (tui_commands[i].key == key)
{
- /* Must save the command because it can be modified by
- execute_command. */
- char *cmd = alloca (strlen (tui_commands[i].cmd) + 1);
- strcpy (cmd, tui_commands[i].cmd);
- execute_command (cmd, TRUE);
+ /* Insert the command in the readline buffer.
+ Avoid calling the gdb command here since it creates
+ a possible recursion on readline if prompt_for_continue
+ is called (See PR 9584). The command will also appear
+ in the readline history which turns out to be better. */
+ rl_insert_text (tui_commands[i].cmd);
+ rl_newline (1, '\n');
+
+ /* Switch to gdb command mode while executing the command.
+ This way the gdb's continue prompty will be displayed. */
+ tui_set_key_mode (TUI_ONE_COMMAND_MODE);
return 0;
}
}
@@ -286,7 +300,8 @@ static int
tui_rl_startup_hook (void)
{
rl_already_prompted = 1;
- if (tui_current_key_mode != TUI_COMMAND_MODE)
+ if (tui_current_key_mode != TUI_COMMAND_MODE
+ && !gdb_in_secondary_prompt_p (current_ui))
tui_set_key_mode (TUI_SINGLE_KEY_MODE);
tui_redisplay_readline ();
return 0;
@@ -311,13 +326,19 @@ tui_initialize_readline (void)
int i;
Keymap tui_ctlx_keymap;
- rl_initialize ();
-
rl_add_defun ("tui-switch-mode", tui_rl_switch_mode, -1);
- rl_add_defun ("gdb-command", tui_rl_command_key, -1);
rl_add_defun ("next-keymap", tui_rl_next_keymap, -1);
+ rl_add_defun ("tui-delete-other-windows", tui_rl_delete_other_windows, -1);
+ rl_add_defun ("tui-change-windows", tui_rl_change_windows, -1);
+ rl_add_defun ("tui-other-window", tui_rl_other_window, -1);
tui_keymap = rl_make_bare_keymap ();
+
+ /* The named keymap feature was added in Readline 8.0. */
+#if RL_READLINE_VERSION >= 0x800
+ rl_set_keymap_name ("SingleKey", tui_keymap);
+#endif
+
tui_ctlx_keymap = rl_make_bare_keymap ();
tui_readline_standard_keymap = rl_get_keymap ();
@@ -359,6 +380,20 @@ tui_initialize_readline (void)
rl_bind_key_in_map ('s', tui_rl_next_keymap, tui_ctlx_keymap);
}
+/* Return the TERM variable from the environment, or ""
+ if not set. */
+
+static const char *
+gdb_getenv_term (void)
+{
+ const char *term;
+
+ term = getenv ("TERM");
+ if (term != NULL)
+ return term;
+ return "";
+}
+
/* Enter in the tui mode (curses).
When in normal mode, it installs the tui hooks in gdb, redirects
the gdb output, configures the readline to work in tui mode.
@@ -369,32 +404,82 @@ tui_enable (void)
if (tui_active)
return;
- /* To avoid to initialize curses when gdb starts, there is a defered
+ /* To avoid to initialize curses when gdb starts, there is a deferred
curses initialization. This initialization is made only once
and the first time the curses mode is entered. */
if (tui_finish_init)
{
WINDOW *w;
+ SCREEN *s;
+#ifndef __MINGW32__
+ const char *cap;
+#endif
+ const char *interp;
+
+ /* If the top level interpreter is not the console/tui (e.g.,
+ MI), enabling curses will certainly lose. */
+ interp = top_level_interpreter ()->name ();
+ if (strcmp (interp, INTERP_TUI) != 0)
+ error (_("Cannot enable the TUI when the interpreter is '%s'"), interp);
+
+ /* Don't try to setup curses (and print funny control
+ characters) if we're not outputting to a terminal. */
+ if (!ui_file_isatty (gdb_stdout))
+ error (_("Cannot enable the TUI when output is not a terminal"));
+
+ s = newterm (NULL, stdout, stdin);
+#ifdef __MINGW32__
+ /* The MinGW port of ncurses requires $TERM to be unset in order
+ to activate the Windows console driver. */
+ if (s == NULL)
+ s = newterm ((char *) "unknown", stdout, stdin);
+#endif
+ if (s == NULL)
+ {
+ error (_("Cannot enable the TUI: error opening terminal [TERM=%s]"),
+ gdb_getenv_term ());
+ }
+ w = stdscr;
+ if (has_colors ())
+ {
+#ifdef HAVE_USE_DEFAULT_COLORS
+ /* Ncurses extension to help with resetting to the default
+ color. */
+ use_default_colors ();
+#endif
+ start_color ();
+ }
+
+ /* Check required terminal capabilities. The MinGW port of
+ ncurses does have them, but doesn't expose them through "cup". */
+#ifndef __MINGW32__
+ cap = tigetstr ((char *) "cup");
+ if (cap == NULL || cap == (char *) -1 || *cap == '\0')
+ {
+ endwin ();
+ delscreen (s);
+ error (_("Cannot enable the TUI: "
+ "terminal doesn't support cursor addressing [TERM=%s]"),
+ gdb_getenv_term ());
+ }
+#endif
- w = initscr ();
-
cbreak ();
noecho ();
/* timeout (1); */
nodelay(w, FALSE);
nl();
keypad (w, TRUE);
- rl_initialize ();
tui_set_term_height_to (LINES);
tui_set_term_width_to (COLS);
def_prog_mode ();
tui_show_frame_info (0);
- tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
+ tui_set_layout (SRC_COMMAND);
tui_set_win_focus_to (TUI_SRC_WIN);
- keypad (TUI_CMD_WIN->generic.handle, TRUE);
- wrefresh (TUI_CMD_WIN->generic.handle);
- tui_finish_init = 0;
+ keypad (TUI_CMD_WIN->handle.get (), TRUE);
+ wrefresh (TUI_CMD_WIN->handle.get ());
+ tui_finish_init = false;
}
else
{
@@ -404,24 +489,40 @@ tui_enable (void)
clearok (stdscr, TRUE);
}
- /* Install the TUI specific hooks. */
- tui_install_hooks ();
- rl_startup_hook = tui_rl_startup_hook;
+ if (tui_update_variables ())
+ tui_rehighlight_all ();
- tui_update_variables ();
-
tui_setup_io (1);
- tui_active = 1;
+ tui_active = true;
+
+ /* Resize windows before anything might display/refresh a
+ window. */
+ if (tui_win_resized ())
+ {
+ tui_set_win_resized_to (false);
+ tui_resize_all ();
+ }
+
if (deprecated_safe_get_selected_frame ())
- tui_show_frame_info (deprecated_safe_get_selected_frame ());
+ tui_show_frame_info (deprecated_safe_get_selected_frame ());
+ else
+ tui_display_main ();
+
+ /* Install the TUI specific hooks. This must be done after the call to
+ tui_display_main so that we don't detect the symtab changed event it
+ can cause. */
+ tui_install_hooks ();
+ rl_startup_hook = tui_rl_startup_hook;
/* Restore TUI keymap. */
tui_set_key_mode (tui_current_key_mode);
+
+ /* Refresh the screen. */
tui_refresh_all_win ();
/* Update gdb's knowledge of its terminal. */
- target_terminal_save_ours ();
+ gdb_save_tty_state ();
tui_update_gdb_sizes ();
}
@@ -451,120 +552,70 @@ tui_disable (void)
tui_setup_io (0);
/* Update gdb's knowledge of its terminal. */
- target_terminal_save_ours ();
+ gdb_save_tty_state ();
- tui_active = 0;
+ tui_active = false;
tui_update_gdb_sizes ();
}
-void
-strcat_to_buf (char *buf, int buflen,
- const char *item_to_add)
-{
- if (item_to_add != (char *) NULL && buf != (char *) NULL)
- {
- if ((strlen (buf) + strlen (item_to_add)) <= buflen)
- strcat (buf, item_to_add);
- else
- strncat (buf, item_to_add, (buflen - strlen (buf)));
- }
-}
-
-#if 0
-/* Solaris defines CTRL. */
-#ifndef CTRL
-#define CTRL(x) (x & ~0140)
-#endif
-
-#define FILEDES 2
-#define CHK(val, dft) (val<=0 ? dft : val)
+/* Command wrapper for enabling tui mode. */
static void
-tui_reset (void)
+tui_enable_command (const char *args, int from_tty)
{
- struct termio mode;
-
- /* Reset the teletype mode bits to a sensible state.
- Copied tset.c. */
-#if defined (TIOCGETC)
- struct tchars tbuf;
-#endif /* TIOCGETC */
-#ifdef UCB_NTTY
- struct ltchars ltc;
-
- if (ldisc == NTTYDISC)
- {
- ioctl (FILEDES, TIOCGLTC, <c);
- ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z'));
- ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y'));
- ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R'));
- ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O'));
- ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W'));
- ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V'));
- ioctl (FILEDES, TIOCSLTC, <c);
- }
-#endif /* UCB_NTTY */
-#ifdef TIOCGETC
- ioctl (FILEDES, TIOCGETC, &tbuf);
- tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
- tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\'));
- tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q'));
- tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S'));
- tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D'));
- /* brkc is left alone. */
- ioctl (FILEDES, TIOCSETC, &tbuf);
-#endif /* TIOCGETC */
- mode.sg_flags &= ~(RAW
-#ifdef CBREAK
- | CBREAK
-#endif /* CBREAK */
- | VTDELAY | ALLDELAY);
- mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
-
- return;
+ tui_enable ();
}
-#endif
-void
-tui_show_source (const char *file, int line)
-{
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
- /* Make sure that the source window is displayed. */
- tui_add_win_to_layout (SRC_WIN);
+/* Command wrapper for leaving tui mode. */
- tui_update_source_windows_with_line (cursal.symtab, line);
- tui_update_locator_filename (file);
+static void
+tui_disable_command (const char *args, int from_tty)
+{
+ tui_disable ();
}
void
-tui_show_assembly (CORE_ADDR addr)
+tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
{
tui_add_win_to_layout (DISASSEM_WIN);
- tui_update_source_windows_with_addr (addr);
+ tui_update_source_windows_with_addr (gdbarch, addr);
}
-int
+bool
tui_is_window_visible (enum tui_win_type type)
{
- if (tui_active == 0)
- return 0;
+ if (!tui_active)
+ return false;
if (tui_win_list[type] == 0)
- return 0;
+ return false;
- return tui_win_list[type]->generic.is_visible;
+ return tui_win_list[type]->is_visible ();
}
-int
+bool
tui_get_command_dimension (unsigned int *width,
unsigned int *height)
{
if (!tui_active || (TUI_CMD_WIN == NULL))
- {
- return 0;
- }
+ return false;
- *width = TUI_CMD_WIN->generic.width;
- *height = TUI_CMD_WIN->generic.height;
- return 1;
+ *width = TUI_CMD_WIN->width;
+ *height = TUI_CMD_WIN->height;
+ return true;
+}
+
+void
+_initialize_tui (void)
+{
+ struct cmd_list_element **tuicmd;
+
+ tuicmd = tui_get_cmd_list ();
+
+ add_cmd ("enable", class_tui, tui_enable_command,
+ _("Enable TUI display mode."),
+ tuicmd);
+ add_cmd ("disable", class_tui, tui_disable_command,
+ _("Disable TUI display mode."),
+ tuicmd);
}