GDB (API)
|
00001 /* General functions for the WDB TUI. 00002 00003 Copyright (C) 1998-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Hewlett-Packard Company. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "gdbcmd.h" 00024 #include "tui/tui.h" 00025 #include "tui/tui-hooks.h" 00026 #include "tui/tui-data.h" 00027 #include "tui/tui-layout.h" 00028 #include "tui/tui-io.h" 00029 #include "tui/tui-regs.h" 00030 #include "tui/tui-stack.h" 00031 #include "tui/tui-win.h" 00032 #include "tui/tui-winsource.h" 00033 #include "tui/tui-windata.h" 00034 #include "target.h" 00035 #include "frame.h" 00036 #include "breakpoint.h" 00037 #include "inferior.h" 00038 #include "symtab.h" 00039 #include "source.h" 00040 00041 #include <stdio.h> 00042 #include <stdlib.h> 00043 #include <ctype.h> 00044 #include <signal.h> 00045 #include <fcntl.h> 00046 #if 0 00047 #include <termio.h> 00048 #endif 00049 #include <setjmp.h> 00050 00051 #include "gdb_curses.h" 00052 00053 /* This redefines CTRL if it is not already defined, so it must come 00054 after terminal state releated include files like <term.h> and 00055 "gdb_curses.h". */ 00056 #include "readline/readline.h" 00057 00058 /* Tells whether the TUI is active or not. */ 00059 int tui_active = 0; 00060 static int tui_finish_init = 1; 00061 00062 enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE; 00063 00064 struct tui_char_command 00065 { 00066 unsigned char key; 00067 const char *cmd; 00068 }; 00069 00070 /* Key mapping to gdb commands when the TUI is using the single key 00071 mode. */ 00072 static const struct tui_char_command tui_commands[] = { 00073 { 'c', "continue" }, 00074 { 'd', "down" }, 00075 { 'f', "finish" }, 00076 { 'n', "next" }, 00077 { 'r', "run" }, 00078 { 's', "step" }, 00079 { 'u', "up" }, 00080 { 'v', "info locals" }, 00081 { 'w', "where" }, 00082 { 0, 0 }, 00083 }; 00084 00085 static Keymap tui_keymap; 00086 static Keymap tui_readline_standard_keymap; 00087 00088 /* TUI readline command. 00089 Switch the output mode between TUI/standard gdb. */ 00090 static int 00091 tui_rl_switch_mode (int notused1, int notused2) 00092 { 00093 if (tui_active) 00094 { 00095 tui_disable (); 00096 rl_prep_terminal (0); 00097 } 00098 else 00099 { 00100 rl_deprep_terminal (); 00101 tui_enable (); 00102 } 00103 00104 /* Clear the readline in case switching occurred in middle of 00105 something. */ 00106 if (rl_end) 00107 rl_kill_text (0, rl_end); 00108 00109 /* Since we left the curses mode, the terminal mode is restored to 00110 some previous state. That state may not be suitable for readline 00111 to work correctly (it may be restored in line mode). We force an 00112 exit of the current readline so that readline is re-entered and 00113 it will be able to setup the terminal for its needs. By 00114 re-entering in readline, we also redisplay its prompt in the 00115 non-curses mode. */ 00116 rl_newline (1, '\n'); 00117 00118 /* Make sure the \n we are returning does not repeat the last 00119 command. */ 00120 dont_repeat (); 00121 return 0; 00122 } 00123 00124 /* TUI readline command. 00125 Change the TUI layout to show a next layout. 00126 This function is bound to CTRL-X 2. It is intended to provide 00127 a functionality close to the Emacs split-window command. We 00128 always show two windows (src+asm), (src+regs) or (asm+regs). */ 00129 static int 00130 tui_rl_change_windows (int notused1, int notused2) 00131 { 00132 if (!tui_active) 00133 tui_rl_switch_mode (0 /* notused */, 0 /* notused */); 00134 00135 if (tui_active) 00136 { 00137 enum tui_layout_type new_layout; 00138 enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS; 00139 00140 new_layout = tui_current_layout (); 00141 00142 /* Select a new layout to have a rolling layout behavior with 00143 always two windows (except when undefined). */ 00144 switch (new_layout) 00145 { 00146 case SRC_COMMAND: 00147 new_layout = SRC_DISASSEM_COMMAND; 00148 break; 00149 00150 case DISASSEM_COMMAND: 00151 new_layout = SRC_DISASSEM_COMMAND; 00152 break; 00153 00154 case SRC_DATA_COMMAND: 00155 new_layout = SRC_DISASSEM_COMMAND; 00156 break; 00157 00158 case SRC_DISASSEM_COMMAND: 00159 new_layout = DISASSEM_DATA_COMMAND; 00160 break; 00161 00162 case DISASSEM_DATA_COMMAND: 00163 new_layout = SRC_DATA_COMMAND; 00164 break; 00165 00166 default: 00167 new_layout = SRC_COMMAND; 00168 break; 00169 } 00170 tui_set_layout (new_layout, regs_type); 00171 } 00172 return 0; 00173 } 00174 00175 /* TUI readline command. 00176 Delete the second TUI window to only show one. */ 00177 static int 00178 tui_rl_delete_other_windows (int notused1, int notused2) 00179 { 00180 if (!tui_active) 00181 tui_rl_switch_mode (0 /* notused */, 0 /* notused */); 00182 00183 if (tui_active) 00184 { 00185 enum tui_layout_type new_layout; 00186 enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS; 00187 00188 new_layout = tui_current_layout (); 00189 00190 /* Kill one window. */ 00191 switch (new_layout) 00192 { 00193 case SRC_COMMAND: 00194 case SRC_DATA_COMMAND: 00195 case SRC_DISASSEM_COMMAND: 00196 default: 00197 new_layout = SRC_COMMAND; 00198 break; 00199 00200 case DISASSEM_COMMAND: 00201 case DISASSEM_DATA_COMMAND: 00202 new_layout = DISASSEM_COMMAND; 00203 break; 00204 } 00205 tui_set_layout (new_layout, regs_type); 00206 } 00207 return 0; 00208 } 00209 00210 /* TUI readline command. 00211 Switch the active window to give the focus to a next window. */ 00212 static int 00213 tui_rl_other_window (int count, int key) 00214 { 00215 struct tui_win_info *win_info; 00216 00217 if (!tui_active) 00218 tui_rl_switch_mode (0 /* notused */, 0 /* notused */); 00219 00220 win_info = tui_next_win (tui_win_with_focus ()); 00221 if (win_info) 00222 { 00223 tui_set_win_focus_to (win_info); 00224 if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible) 00225 tui_refresh_data_win (); 00226 keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN)); 00227 } 00228 return 0; 00229 } 00230 00231 /* TUI readline command. 00232 Execute the gdb command bound to the specified key. */ 00233 static int 00234 tui_rl_command_key (int count, int key) 00235 { 00236 int i; 00237 00238 reinitialize_more_filter (); 00239 for (i = 0; tui_commands[i].cmd; i++) 00240 { 00241 if (tui_commands[i].key == key) 00242 { 00243 /* Insert the command in the readline buffer. 00244 Avoid calling the gdb command here since it creates 00245 a possible recursion on readline if prompt_for_continue 00246 is called (See PR 9584). The command will also appear 00247 in the readline history which turns out to be better. */ 00248 rl_insert_text (tui_commands[i].cmd); 00249 rl_newline (1, '\n'); 00250 00251 /* Switch to gdb command mode while executing the command. 00252 This way the gdb's continue prompty will be displayed. */ 00253 tui_set_key_mode (TUI_ONE_COMMAND_MODE); 00254 return 0; 00255 } 00256 } 00257 return 0; 00258 } 00259 00260 /* TUI readline command. 00261 Temporarily leave the TUI SingleKey mode to allow editing 00262 a gdb command with the normal readline. Once the command 00263 is executed, the TUI SingleKey mode is installed back. */ 00264 static int 00265 tui_rl_command_mode (int count, int key) 00266 { 00267 tui_set_key_mode (TUI_ONE_COMMAND_MODE); 00268 return rl_insert (count, key); 00269 } 00270 00271 /* TUI readline command. 00272 Switch between TUI SingleKey mode and gdb readline editing. */ 00273 static int 00274 tui_rl_next_keymap (int notused1, int notused2) 00275 { 00276 if (!tui_active) 00277 tui_rl_switch_mode (0 /* notused */, 0 /* notused */); 00278 00279 tui_set_key_mode (tui_current_key_mode == TUI_COMMAND_MODE 00280 ? TUI_SINGLE_KEY_MODE : TUI_COMMAND_MODE); 00281 return 0; 00282 } 00283 00284 /* Readline hook to redisplay ourself the gdb prompt. 00285 In the SingleKey mode, the prompt is not printed so that 00286 the command window is cleaner. It will be displayed if 00287 we temporarily leave the SingleKey mode. */ 00288 static int 00289 tui_rl_startup_hook (void) 00290 { 00291 rl_already_prompted = 1; 00292 if (tui_current_key_mode != TUI_COMMAND_MODE && immediate_quit == 0) 00293 tui_set_key_mode (TUI_SINGLE_KEY_MODE); 00294 tui_redisplay_readline (); 00295 return 0; 00296 } 00297 00298 /* Change the TUI key mode by installing the appropriate readline 00299 keymap. */ 00300 void 00301 tui_set_key_mode (enum tui_key_mode mode) 00302 { 00303 tui_current_key_mode = mode; 00304 rl_set_keymap (mode == TUI_SINGLE_KEY_MODE 00305 ? tui_keymap : tui_readline_standard_keymap); 00306 tui_show_locator_content (); 00307 } 00308 00309 /* Initialize readline and configure the keymap for the switching 00310 key shortcut. */ 00311 void 00312 tui_initialize_readline (void) 00313 { 00314 int i; 00315 Keymap tui_ctlx_keymap; 00316 00317 rl_initialize (); 00318 00319 rl_add_defun ("tui-switch-mode", tui_rl_switch_mode, -1); 00320 rl_add_defun ("gdb-command", tui_rl_command_key, -1); 00321 rl_add_defun ("next-keymap", tui_rl_next_keymap, -1); 00322 00323 tui_keymap = rl_make_bare_keymap (); 00324 tui_ctlx_keymap = rl_make_bare_keymap (); 00325 tui_readline_standard_keymap = rl_get_keymap (); 00326 00327 for (i = 0; tui_commands[i].cmd; i++) 00328 rl_bind_key_in_map (tui_commands[i].key, tui_rl_command_key, tui_keymap); 00329 00330 rl_generic_bind (ISKMAP, "\\C-x", (char*) tui_ctlx_keymap, tui_keymap); 00331 00332 /* Bind all other keys to tui_rl_command_mode so that we switch 00333 temporarily from SingleKey mode and can enter a gdb command. */ 00334 for (i = ' '; i < 0x7f; i++) 00335 { 00336 int j; 00337 00338 for (j = 0; tui_commands[j].cmd; j++) 00339 if (tui_commands[j].key == i) 00340 break; 00341 00342 if (tui_commands[j].cmd) 00343 continue; 00344 00345 rl_bind_key_in_map (i, tui_rl_command_mode, tui_keymap); 00346 } 00347 00348 rl_bind_key_in_map ('a', tui_rl_switch_mode, emacs_ctlx_keymap); 00349 rl_bind_key_in_map ('a', tui_rl_switch_mode, tui_ctlx_keymap); 00350 rl_bind_key_in_map ('A', tui_rl_switch_mode, emacs_ctlx_keymap); 00351 rl_bind_key_in_map ('A', tui_rl_switch_mode, tui_ctlx_keymap); 00352 rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, emacs_ctlx_keymap); 00353 rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, tui_ctlx_keymap); 00354 rl_bind_key_in_map ('1', tui_rl_delete_other_windows, emacs_ctlx_keymap); 00355 rl_bind_key_in_map ('1', tui_rl_delete_other_windows, tui_ctlx_keymap); 00356 rl_bind_key_in_map ('2', tui_rl_change_windows, emacs_ctlx_keymap); 00357 rl_bind_key_in_map ('2', tui_rl_change_windows, tui_ctlx_keymap); 00358 rl_bind_key_in_map ('o', tui_rl_other_window, emacs_ctlx_keymap); 00359 rl_bind_key_in_map ('o', tui_rl_other_window, tui_ctlx_keymap); 00360 rl_bind_key_in_map ('q', tui_rl_next_keymap, tui_keymap); 00361 rl_bind_key_in_map ('s', tui_rl_next_keymap, emacs_ctlx_keymap); 00362 rl_bind_key_in_map ('s', tui_rl_next_keymap, tui_ctlx_keymap); 00363 } 00364 00365 /* Enter in the tui mode (curses). 00366 When in normal mode, it installs the tui hooks in gdb, redirects 00367 the gdb output, configures the readline to work in tui mode. 00368 When in curses mode, it does nothing. */ 00369 void 00370 tui_enable (void) 00371 { 00372 if (!tui_allowed_p ()) 00373 error (_("TUI mode not allowed")); 00374 00375 if (tui_active) 00376 return; 00377 00378 /* To avoid to initialize curses when gdb starts, there is a defered 00379 curses initialization. This initialization is made only once 00380 and the first time the curses mode is entered. */ 00381 if (tui_finish_init) 00382 { 00383 WINDOW *w; 00384 00385 w = initscr (); 00386 00387 cbreak (); 00388 noecho (); 00389 /* timeout (1); */ 00390 nodelay(w, FALSE); 00391 nl(); 00392 keypad (w, TRUE); 00393 rl_initialize (); 00394 tui_set_term_height_to (LINES); 00395 tui_set_term_width_to (COLS); 00396 def_prog_mode (); 00397 00398 tui_show_frame_info (0); 00399 tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS); 00400 tui_set_win_focus_to (TUI_SRC_WIN); 00401 keypad (TUI_CMD_WIN->generic.handle, TRUE); 00402 wrefresh (TUI_CMD_WIN->generic.handle); 00403 tui_finish_init = 0; 00404 } 00405 else 00406 { 00407 /* Save the current gdb setting of the terminal. 00408 Curses will restore this state when endwin() is called. */ 00409 def_shell_mode (); 00410 clearok (stdscr, TRUE); 00411 } 00412 00413 /* Install the TUI specific hooks. */ 00414 tui_install_hooks (); 00415 rl_startup_hook = tui_rl_startup_hook; 00416 00417 tui_update_variables (); 00418 00419 tui_setup_io (1); 00420 00421 tui_active = 1; 00422 if (deprecated_safe_get_selected_frame ()) 00423 tui_show_frame_info (deprecated_safe_get_selected_frame ()); 00424 00425 /* Restore TUI keymap. */ 00426 tui_set_key_mode (tui_current_key_mode); 00427 tui_refresh_all_win (); 00428 00429 /* Update gdb's knowledge of its terminal. */ 00430 target_terminal_save_ours (); 00431 tui_update_gdb_sizes (); 00432 } 00433 00434 /* Leave the tui mode. 00435 Remove the tui hooks and configure the gdb output and readline 00436 back to their original state. The curses mode is left so that 00437 the terminal setting is restored to the point when we entered. */ 00438 void 00439 tui_disable (void) 00440 { 00441 if (!tui_active) 00442 return; 00443 00444 /* Restore initial readline keymap. */ 00445 rl_set_keymap (tui_readline_standard_keymap); 00446 00447 /* Remove TUI hooks. */ 00448 tui_remove_hooks (); 00449 rl_startup_hook = 0; 00450 rl_already_prompted = 0; 00451 00452 /* Leave curses and restore previous gdb terminal setting. */ 00453 endwin (); 00454 00455 /* gdb terminal has changed, update gdb internal copy of it 00456 so that terminal management with the inferior works. */ 00457 tui_setup_io (0); 00458 00459 /* Update gdb's knowledge of its terminal. */ 00460 target_terminal_save_ours (); 00461 00462 tui_active = 0; 00463 tui_update_gdb_sizes (); 00464 } 00465 00466 void 00467 strcat_to_buf (char *buf, int buflen, 00468 const char *item_to_add) 00469 { 00470 if (item_to_add != (char *) NULL && buf != (char *) NULL) 00471 { 00472 if ((strlen (buf) + strlen (item_to_add)) <= buflen) 00473 strcat (buf, item_to_add); 00474 else 00475 strncat (buf, item_to_add, (buflen - strlen (buf))); 00476 } 00477 } 00478 00479 #if 0 00480 /* Solaris <sys/termios.h> defines CTRL. */ 00481 #ifndef CTRL 00482 #define CTRL(x) (x & ~0140) 00483 #endif 00484 00485 #define FILEDES 2 00486 #define CHK(val, dft) (val<=0 ? dft : val) 00487 00488 static void 00489 tui_reset (void) 00490 { 00491 struct termio mode; 00492 00493 /* Reset the teletype mode bits to a sensible state. 00494 Copied tset.c. */ 00495 #if defined (TIOCGETC) 00496 struct tchars tbuf; 00497 #endif /* TIOCGETC */ 00498 #ifdef UCB_NTTY 00499 struct ltchars ltc; 00500 00501 if (ldisc == NTTYDISC) 00502 { 00503 ioctl (FILEDES, TIOCGLTC, <c); 00504 ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z')); 00505 ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y')); 00506 ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R')); 00507 ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O')); 00508 ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W')); 00509 ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V')); 00510 ioctl (FILEDES, TIOCSLTC, <c); 00511 } 00512 #endif /* UCB_NTTY */ 00513 #ifdef TIOCGETC 00514 ioctl (FILEDES, TIOCGETC, &tbuf); 00515 tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?')); 00516 tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\')); 00517 tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q')); 00518 tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S')); 00519 tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D')); 00520 /* brkc is left alone. */ 00521 ioctl (FILEDES, TIOCSETC, &tbuf); 00522 #endif /* TIOCGETC */ 00523 mode.sg_flags &= ~(RAW 00524 #ifdef CBREAK 00525 | CBREAK 00526 #endif /* CBREAK */ 00527 | VTDELAY | ALLDELAY); 00528 mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP; 00529 00530 return; 00531 } 00532 #endif 00533 00534 void 00535 tui_show_source (const char *fullname, int line) 00536 { 00537 struct symtab_and_line cursal = get_current_source_symtab_and_line (); 00538 00539 /* Make sure that the source window is displayed. */ 00540 tui_add_win_to_layout (SRC_WIN); 00541 00542 tui_update_source_windows_with_line (cursal.symtab, line); 00543 tui_update_locator_fullname (fullname); 00544 } 00545 00546 void 00547 tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr) 00548 { 00549 tui_add_win_to_layout (DISASSEM_WIN); 00550 tui_update_source_windows_with_addr (gdbarch, addr); 00551 } 00552 00553 int 00554 tui_is_window_visible (enum tui_win_type type) 00555 { 00556 if (tui_active == 0) 00557 return 0; 00558 00559 if (tui_win_list[type] == 0) 00560 return 0; 00561 00562 return tui_win_list[type]->generic.is_visible; 00563 } 00564 00565 int 00566 tui_get_command_dimension (unsigned int *width, 00567 unsigned int *height) 00568 { 00569 if (!tui_active || (TUI_CMD_WIN == NULL)) 00570 { 00571 return 0; 00572 } 00573 00574 *width = TUI_CMD_WIN->generic.width; 00575 *height = TUI_CMD_WIN->generic.height; 00576 return 1; 00577 }