3c216924d6
Due to the way that readline's API works (based on globals), we can only have one instance of readline in a process. So the goal of this patch is to only allow editing in the main UI, and make sure that only one UI calls into readline. Some MI paths touch readline variables currently, which is bad as that is changing variables that matter for the main console UI. This patch fixes those. This actually fixes a nasty bug -- starting gdb in MI mode ("gdb -i=mi"), and then doing "set editing on" crashes GDB, because MI is not prepared to use readline: set editing on &"set editing on\n" =cmd-param-changed,param="editing",value="on" ^done (gdb) p 1 readline: readline_callback_read_char() called with no handler! Aborted (core dumped) The fix for that was to add an interp_proc method to query the interpreter whether it actually supports editing. New test included. gdb/ChangeLog: 2016-06-21 Pedro Alves <palves@redhat.com> PR mi/20034 * cli/cli-interp.c: Include cli-interp.h and event-top.h. (cli_interpreter_resume): Pass 1 to gdb_setup_readline. Set the UI's input_handler here. (cli_interpreter_supports_command_editing): New function. (cli_interp_procs): Install it. * cli/cli-interp.h: New file. * event-top.c (async_command_editing_p): Rename to ... (set_editing_cmd_var): ... this. (change_line_handler): Add parameter 'editing', and use it. Bail early if the interpreter doesn't support editing. Don't touch readline state if editing is off. (gdb_rl_callback_handler_remove, gdb_rl_callback_handler_install) (gdb_rl_callback_handler_reinstall): Assert the current UI is the main UI. (display_gdb_prompt): Don't call gdb_rl_callback_handler_remove if not using readline. Check whether the current UI is using command editing instead of checking the async_command_editing_p global. (set_async_editing_command): Delete. (gdb_setup_readline): Add 'editing' parameter. Only allow editing on the main UI. Don't touch readline state if editing is off. (gdb_disable_readline): Don't touch readline state if editing is off. * event-top.h (gdb_setup_readline): Add 'int' parameter. (set_async_editing_command): Delete declaration. (change_line_handler, command_line_handler): Declare. (async_command_editing_p): Rename to ... (set_editing_cmd_var): ... this. * infrun.c (reinstall_readline_callback_handler_cleanup): Check whether the current UI has editing enabled rather than checking the async_command_editing_p global. * interps.c (interp_supports_command_editing): New function. * interps.h (interp_supports_command_editing_ftype): New typedef. (struct interp_procs) <supports_command_editing_proc>: New field. (interp_supports_command_editing): Declare. * mi/mi-interp.c (mi_interpreter_resume): Pass 0 to gdb_setup_readline. Don't clear the async_command_editing_p global. Update comments. * top.c (gdb_readline_wrapper_line, gdb_readline_wrapper): Check whether the current UI has editing enabled rather than checking the async_command_editing_p global. Don't touch readline state if editing is off. (undo_terminal_modifications_before_exit): Switch to the main UI. Unconditionally call gdb_disable_readline. (set_editing): New function. (show_async_command_editing_p): Rename to ... (show_editing): ... this. Show the state of the current UI. (_initialize_top): Adjust. * top.h (struct ui) <command_editing>: New field. * tui/tui-interp.c: Include cli/cli-interp.h. (tui_resume): Pass 1 to gdb_setup_readline. Set the UI's input_handler. (tui_interp_procs): Install cli_interpreter_supports_command_editing. * tui/tui-io.c (tui_getc): Check whether the current UI has editing enabled rather than checking the async_command_editing_p global. gdb/testsuite/ChangeLog: 2016-06-21 Pedro Alves <palves@redhat.com> PR mi/20034 * gdb.mi/mi-editing.exp: New file.
77 lines
2.6 KiB
C
77 lines
2.6 KiB
C
/* Definitions used by event-top.c, for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 1999-2016 Free Software Foundation, Inc.
|
|
|
|
Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
|
|
|
|
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/>. */
|
|
|
|
#ifndef EVENT_TOP_H
|
|
#define EVENT_TOP_H
|
|
|
|
struct cmd_list_element;
|
|
|
|
/* Exported functions from event-top.c.
|
|
FIXME: these should really go into top.h. */
|
|
|
|
extern void display_gdb_prompt (const char *new_prompt);
|
|
extern void gdb_setup_readline (int);
|
|
extern void gdb_disable_readline (void);
|
|
extern void async_init_signals (void);
|
|
extern void change_line_handler (int);
|
|
|
|
extern void command_line_handler (char *rl);
|
|
extern void command_handler (char *command);
|
|
|
|
/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */
|
|
#ifndef STOP_SIGNAL
|
|
#include <signal.h>
|
|
#ifdef SIGTSTP
|
|
#define STOP_SIGNAL SIGTSTP
|
|
extern void handle_stop_sig (int sig);
|
|
#endif
|
|
#endif
|
|
extern void handle_sigint (int sig);
|
|
extern void handle_sigterm (int sig);
|
|
extern void async_request_quit (void *arg);
|
|
extern void stdin_event_handler (int error, void *client_data);
|
|
extern void async_disable_stdin (void);
|
|
extern void async_enable_stdin (void);
|
|
|
|
/* Exported variables from event-top.c.
|
|
FIXME: these should really go into top.h. */
|
|
|
|
extern int set_editing_cmd_var;
|
|
extern int exec_done_display_p;
|
|
extern struct prompts the_prompts;
|
|
extern void (*after_char_processing_hook) (void);
|
|
extern int call_stdin_event_handler_again_p;
|
|
extern void gdb_readline_no_editing_callback (void *client_data);
|
|
|
|
/* Wrappers for rl_callback_handler_remove and
|
|
rl_callback_handler_install that keep track of whether the callback
|
|
handler is installed in readline. Do not call the readline
|
|
versions directly. */
|
|
extern void gdb_rl_callback_handler_remove (void);
|
|
extern void gdb_rl_callback_handler_install (const char *prompt);
|
|
|
|
/* Reinstall the readline callback handler (with no prompt), if not
|
|
currently installed. */
|
|
extern void gdb_rl_callback_handler_reinstall (void);
|
|
|
|
extern void cli_command_loop (void *);
|
|
|
|
#endif
|