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); }