2003-02-06 06:30:17 +01:00
|
|
|
/* Manages interpreters for GDB, the GNU debugger.
|
|
|
|
|
2017-01-01 07:50:51 +01:00
|
|
|
Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
2003-02-06 06:30:17 +01:00
|
|
|
|
|
|
|
Written by Jim Ingham <jingham@apple.com> of Apple Computer, Inc.
|
|
|
|
|
|
|
|
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
|
2007-08-23 20:08:50 +02:00
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
2003-02-06 06:30:17 +01:00
|
|
|
(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
|
2011-01-09 04:08:57 +01:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2003-02-06 06:30:17 +01:00
|
|
|
|
|
|
|
#ifndef INTERPS_H
|
|
|
|
#define INTERPS_H
|
|
|
|
|
|
|
|
struct ui_out;
|
|
|
|
struct interp;
|
Introduce interpreter factories
If every UI instance has its own set of interpreters, then the current
scheme of creating the interpreters at GDB initialization time no
longer works. We need to create them whenever a new UI instance is
created.
The scheme implemented here has each interpreter register a factory
callback that when called creates a new instance of a specific
interpreter type. Then, when some code in gdb looks up an interpreter
(always by name), if there's none yet, the factory method is called to
construct one.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_uiout): Delete, moved into ...
(struct cli_interp): ... this new structure.
(cli_on_normal_stop, cli_on_signal_received)
(cli_on_end_stepping_range, cli_on_signal_exited, cli_on_exited)
(cli_on_no_history): Use interp_ui_out.
(cli_interpreter_init): If top level, set the cli_interp global.
(cli_interpreter_init): Return the interp's data instead of NULL.
(cli_interpreter_resume, cli_interpreter_exec, cli_ui_out): Adjust
to cli_uiout being in the interpreter's data.
(cli_interp_procs): New, factored out from _initialize_cli_interp.
(cli_interp_factory): New function.
(_initialize_cli_interp): Call interp_factory_register.
* interps.c (get_interp_info): New, factored out from ...
(get_current_interp_info): ... this.
(interp_new): Add parameter 'data'. Store it.
(struct interp_factory): New function.
(interp_factory_p): New typedef. Define a VEC_P.
(interpreter_factories): New global.
(interp_factory_register): New function.
(interp_add): Add 'ui' parameter. Use get_interp_info and
interp_lookup_existing.
(interp_lookup): Rename to ...
(interp_lookup_existing): ... this. Add 'ui' parameter. Don't
check for NULL or empty name here.
(interp_lookup): Add 'ui' parameter and reimplement.
(interp_set_temp, interpreter_exec_cmd): Adjust.
(interpreter_completer): Complete on registered interpreter
factories instead of interpreters.
* interps.h (interp_factory_func): New typedef.
(interp_factory_register): Declare.
(interp_new, interp_add): Adjust.
(interp_lookup): Declare.
* main.c (captured_main): Adjust.
* mi/mi-interp.c (mi_cmd_interpreter_exec): Adjust.
(mi_interp_procs): New, factored out from
_initialize_mi_interp.
(mi_interp_factory): New function.
* python/python.c (execute_gdb_command): Adjust.
* tui/tui-interp.c (tui_init): If top level, set the tui_interp
global.
(tui_interp_procs): New.
(tui_interp_factory): New function.
(_initialize_tui_interp): Call interp_factory_register.
2016-06-21 02:11:45 +02:00
|
|
|
struct ui;
|
|
|
|
|
|
|
|
typedef struct interp *(*interp_factory_func) (const char *name);
|
|
|
|
|
|
|
|
/* Each interpreter kind (CLI, MI, etc.) registers itself with a call
|
|
|
|
to this function, passing along its name, and a pointer to a
|
|
|
|
function that creates a new instance of an interpreter with that
|
|
|
|
name. */
|
|
|
|
extern void interp_factory_register (const char *name,
|
|
|
|
interp_factory_func func);
|
2003-02-06 06:30:17 +01:00
|
|
|
|
|
|
|
extern int interp_resume (struct interp *interp);
|
|
|
|
extern int interp_suspend (struct interp *interp);
|
2005-04-26 07:03:41 +02:00
|
|
|
extern struct gdb_exception interp_exec (struct interp *interp,
|
|
|
|
const char *command);
|
2003-02-06 06:30:17 +01:00
|
|
|
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
class interp
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit interp (const char *name);
|
|
|
|
virtual ~interp () = 0;
|
2003-02-06 06:30:17 +01:00
|
|
|
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual void init (bool top_level)
|
|
|
|
{}
|
2012-06-29 00:11:23 +02:00
|
|
|
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual void resume () = 0;
|
|
|
|
virtual void suspend () = 0;
|
Make command line editing (use of readline) be per UI
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.
2016-06-21 02:11:48 +02:00
|
|
|
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual gdb_exception exec (const char *command) = 0;
|
2011-09-12 23:25:22 +02:00
|
|
|
|
|
|
|
/* Returns the ui_out currently used to collect results for this
|
|
|
|
interpreter. It can be a formatter for stdout, as is the case
|
|
|
|
for the console & mi outputs, or it might be a result
|
|
|
|
formatter. */
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual ui_out *interp_ui_out () = 0;
|
2011-09-12 23:25:22 +02:00
|
|
|
|
2012-06-29 00:11:23 +02:00
|
|
|
/* Provides a hook for interpreters to do any additional
|
|
|
|
setup/cleanup that they might need when logging is enabled or
|
|
|
|
disabled. */
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual void set_logging (ui_file_up logfile, bool logging_redirect) = 0;
|
2012-06-29 00:11:23 +02:00
|
|
|
|
2016-06-21 02:11:51 +02:00
|
|
|
/* Called before starting an event loop, to give the interpreter a
|
|
|
|
chance to e.g., print a prompt. */
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual void pre_command_loop ()
|
|
|
|
{}
|
Make command line editing (use of readline) be per UI
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.
2016-06-21 02:11:48 +02:00
|
|
|
|
|
|
|
/* Returns true if this interpreter supports using the readline
|
|
|
|
library; false if it uses GDB's own simplified readline
|
|
|
|
emulation. */
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
virtual bool supports_command_editing ()
|
|
|
|
{ return false; }
|
|
|
|
|
|
|
|
/* This is the name in "-i=" and "set interpreter". */
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
/* Interpreters are stored in a linked list, this is the next
|
|
|
|
one... */
|
|
|
|
struct interp *next;
|
|
|
|
|
|
|
|
/* Has the init method been run? */
|
|
|
|
bool inited;
|
2003-02-06 06:30:17 +01:00
|
|
|
};
|
|
|
|
|
Introduce interpreter factories
If every UI instance has its own set of interpreters, then the current
scheme of creating the interpreters at GDB initialization time no
longer works. We need to create them whenever a new UI instance is
created.
The scheme implemented here has each interpreter register a factory
callback that when called creates a new instance of a specific
interpreter type. Then, when some code in gdb looks up an interpreter
(always by name), if there's none yet, the factory method is called to
construct one.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_uiout): Delete, moved into ...
(struct cli_interp): ... this new structure.
(cli_on_normal_stop, cli_on_signal_received)
(cli_on_end_stepping_range, cli_on_signal_exited, cli_on_exited)
(cli_on_no_history): Use interp_ui_out.
(cli_interpreter_init): If top level, set the cli_interp global.
(cli_interpreter_init): Return the interp's data instead of NULL.
(cli_interpreter_resume, cli_interpreter_exec, cli_ui_out): Adjust
to cli_uiout being in the interpreter's data.
(cli_interp_procs): New, factored out from _initialize_cli_interp.
(cli_interp_factory): New function.
(_initialize_cli_interp): Call interp_factory_register.
* interps.c (get_interp_info): New, factored out from ...
(get_current_interp_info): ... this.
(interp_new): Add parameter 'data'. Store it.
(struct interp_factory): New function.
(interp_factory_p): New typedef. Define a VEC_P.
(interpreter_factories): New global.
(interp_factory_register): New function.
(interp_add): Add 'ui' parameter. Use get_interp_info and
interp_lookup_existing.
(interp_lookup): Rename to ...
(interp_lookup_existing): ... this. Add 'ui' parameter. Don't
check for NULL or empty name here.
(interp_lookup): Add 'ui' parameter and reimplement.
(interp_set_temp, interpreter_exec_cmd): Adjust.
(interpreter_completer): Complete on registered interpreter
factories instead of interpreters.
* interps.h (interp_factory_func): New typedef.
(interp_factory_register): Declare.
(interp_new, interp_add): Adjust.
(interp_lookup): Declare.
* main.c (captured_main): Adjust.
* mi/mi-interp.c (mi_cmd_interpreter_exec): Adjust.
(mi_interp_procs): New, factored out from
_initialize_mi_interp.
(mi_interp_factory): New function.
* python/python.c (execute_gdb_command): Adjust.
* tui/tui-interp.c (tui_init): If top level, set the tui_interp
global.
(tui_interp_procs): New.
(tui_interp_factory): New function.
(_initialize_tui_interp): Call interp_factory_register.
2016-06-21 02:11:45 +02:00
|
|
|
extern void interp_add (struct ui *ui, struct interp *interp);
|
|
|
|
|
|
|
|
/* Look up the interpreter for NAME, creating one if none exists yet.
|
|
|
|
If NAME is not a interpreter type previously registered with
|
|
|
|
interp_factory_register, return NULL; otherwise return a pointer to
|
|
|
|
the interpreter. */
|
|
|
|
extern struct interp *interp_lookup (struct ui *ui, const char *name);
|
|
|
|
|
Add new command to create extra console/mi UIs
With all the previous plumbing in place, it's now easy to add a
command that actually creates a new console/mi UI.
The intended use case is to make it possible and easy for MI frontends
to provide a fully featured GDB console to users, with readline
support, command line editing, history, etc., just like if gdb was
started on the command line. Currently MI frontends have to try to
implement all of that theirselves and make use of "-interpreter-exec
console ...", which is far from perfect. If you ever tried Eclipse's
gdb console window, you'll know what I mean...
Instead of trying to multiplex console through MI, this command let's
just leverage all the built in readline/editing support already inside
gdb.
The plan is for the MI frontend to start GDB in regular console mode,
running inside a terminal emulator widget embedded in Eclipse (which
already exists, for supporting the shell widget; other frontends have
similar widgets), and then tell GDB to run a full MI interpreter on an
specified input/output device, independent of the console.
My original prototype planned to do things the other way around --
start GDB in MI mode, and then start an extra CLI console on separate
tty. I handed over that prototype to Marc Khouzam @ Eclipse CDT, and
after experimentation and discussion, we ended up concluding that
starting GDB in CLI mode instead was both easier and actually also
supported an interesting use case -- connect an Eclipse frontend to a
GDB that is already running outside Eclipse.
The current usage is "new-ui <interpreter> <tty>".
E.g., on a terminal run this scriplet:
$ cat gdb-client
#!/bin/bash
reset
tty
tail -f /dev/null
$ gdb-client
/dev/pts/15
Now run gdb on another terminal, and tell it to start a MI interpreter
on the tty of the other terminal:
...
(gdb) new-ui mi /dev/pts/15
New UI allocated
Now back to the the gdb-client terminal, we'll get an MI prompt, ready
for MI input:
/dev/pts/15
=thread-group-added,id="i1"
(gdb)
You can also start a new UI running a CLI, with:
(gdb) new-ui console /dev/pts/15
Though note that this console won't support readline command editing.
It works as if "set editing off" was entered.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* interps.c (set_top_level_interpreter): New function, factored
out from captured_main.
(interpreter_completer): Make extern.
* interps.h (set_top_level_interpreter, interpreter_completer):
New declarations.
(captured_main): Use set_top_level_interpreter.
* top.c [!O_NOCTTY] (O_NOCTTY): Define as 0.
(open_terminal_stream, new_ui_command): New functions.
(init_main): Install the "new-ui" command.
2016-06-21 02:11:55 +02:00
|
|
|
/* Set the current UI's top level interpreter to the interpreter named
|
|
|
|
NAME. Throws an error if NAME is not a known interpreter or the
|
|
|
|
interpreter fails to initialize. */
|
|
|
|
extern void set_top_level_interpreter (const char *name);
|
|
|
|
|
2003-02-06 06:30:17 +01:00
|
|
|
extern struct ui_out *interp_ui_out (struct interp *interp);
|
2011-09-12 23:25:22 +02:00
|
|
|
extern const char *interp_name (struct interp *interp);
|
2012-05-08 20:49:42 +02:00
|
|
|
extern struct interp *interp_set_temp (const char *name);
|
2003-02-06 06:30:17 +01:00
|
|
|
|
2017-08-13 22:40:46 +02:00
|
|
|
/* Temporarily set the current interpreter, and reset it on
|
|
|
|
destruction. */
|
|
|
|
class scoped_restore_interp
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
scoped_restore_interp (const char *name)
|
|
|
|
: m_interp (set_interp (name))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~scoped_restore_interp ()
|
|
|
|
{
|
|
|
|
set_interp (interp_name (m_interp));
|
|
|
|
}
|
|
|
|
|
|
|
|
scoped_restore_interp (const scoped_restore_interp &) = delete;
|
|
|
|
scoped_restore_interp &operator= (const scoped_restore_interp &) = delete;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
struct interp *set_interp (const char *name);
|
|
|
|
|
|
|
|
struct interp *m_interp;
|
|
|
|
};
|
|
|
|
|
2003-02-06 06:30:17 +01:00
|
|
|
extern int current_interp_named_p (const char *name);
|
Make display_gdb_prompt CLI-only.
Enabling target-async by default will require implementing sync
execution on top of an async target, much like foreground command are
implemented on the CLI in async mode.
In order to do that, we will need better control of when to print the
MI prompt. Currently the interp->display_prompt_p hook is all we
have, and MI just always returns false, meaning, make
display_gdb_prompt a no-op. We'll need to be able to know to print
the MI prompt in some of the conditions that display_gdb_prompt is
called from the core, but not all.
This is all a litte twisted currently. As we can see,
display_gdb_prompt is really CLI specific, so make the console
interpreters (console/tui) themselves call it. To be able to do that,
and add a few different observers that the interpreters can use to
distinguish when or why the the prompt is being printed:
#1 - one called whenever a command is cancelled due to an error.
#2 - another for when a foreground command just finished.
In both cases, CLI wants to print the prompt, while MI doesn't.
MI will want to print the prompt in the second case when in a special
MI mode.
The display_gdb_prompt call in interp_set made me pause. The comment
there reads:
/* Finally, put up the new prompt to show that we are indeed here.
Also, display_gdb_prompt for the console does some readline magic
which is needed for the console interpreter, at least... */
But, that looks very much like a no-op to me currently:
- the MI interpreter always return false in the prompt hook, meaning
actually display no prompt.
- the interpreter used at that point is still quiet. And the
console/tui interpreters return false in the prompt hook if they're
quiet, meaning actually display no prompt.
The only remaining possible use would then be the readline magic. But
whatever that might have been, it's not reacheable today either,
because display_gdb_prompt returns early, before touching readline if
the interpreter returns false in the display_prompt_p hook.
Tested on x86_64 Fedora 20, sync and async modes.
gdb/
2014-05-29 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interpreter_display_prompt_p): Delete.
(_initialize_cli_interp): Adjust.
* event-loop.c: Include "observer.h".
(start_event_loop): Notify 'command_error' observers instead of
calling display_gdb_prompt. Remove FIXME comment.
* event-top.c (display_gdb_prompt): Remove call into the
interpreters.
* inf-loop.c: Include "observer.h".
(inferior_event_handler): Notify 'command_error' observers instead
of calling display_gdb_prompt.
* infrun.c (fetch_inferior_event): Notify 'sync_execution_done'
observers instead of calling display_gdb_prompt.
* interps.c (interp_set): Don't call display_gdb_prompt.
(current_interp_display_prompt_p): Delete.
* interps.h (interp_prompt_p): Delete declaration.
(interp_prompt_p_ftype): Delete.
(struct interp_procs) <prompt_proc_p>: Delete field.
(current_interp_display_prompt_p): Delete declaration.
* mi-interp.c (mi_interpreter_prompt_p): Delete.
(_initialize_mi_interp): Adjust.
* tui-interp.c (tui_init): Install 'sync_execution_done' and
'command_error' observers.
(tui_on_sync_execution_done, tui_on_command_error): New
functions.
(tui_display_prompt_p): Delete.
(_initialize_tui_interp): Adjust.
gdb/doc/
2014-05-29 Pedro Alves <palves@redhat.com>
* observer.texi (sync_execution_done, command_error): New
subjects.
2014-05-23 12:37:12 +02:00
|
|
|
|
2012-06-29 00:11:23 +02:00
|
|
|
/* Call this function to give the current interpreter an opportunity
|
|
|
|
to do any special handling of streams when logging is enabled or
|
Move "tee" building down to interpreter::set_logging_proc
This patch gets rid of this hack in mi_set_logging:
/* The tee created already is based on gdb_stdout, which for MI
is a console and so we end up in an infinite loop of console
writing to ui_file writing to console etc. So discard the
existing tee (it hasn't been used yet, and MI won't ever use
it), and create one based on raw_stdout instead. */
By pushing down responsibility for the tee creation to the
interpreter. I.e., pushing the CLI bits out of handle_redirections
down to the CLI interpreter's set_logging_proc method.
This fixes a few leaks that I spotted, and then confirmed with
"valgrind --leak-check=full":
[...]
==21429== 56 (32 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 30,243 of 34,980
==21429== at 0x4C29216: operator new(unsigned long) (vg_replace_malloc.c:334)
==21429== by 0x62D9A9: mi_set_logging(interp*, int, ui_file*, ui_file*) (mi-interp.c:1395)
==21429== by 0x810B8A: current_interp_set_logging(int, ui_file*, ui_file*) (interps.c:360)
==21429== by 0x61C537: handle_redirections(int) (cli-logging.c:162)
==21429== by 0x61C6EC: set_logging_on(char*, int) (cli-logging.c:190)
==21429== by 0x6163BE: do_cfunc(cmd_list_element*, char*, int) (cli-decode.c:105)
==21429== by 0x6193C1: cmd_func(cmd_list_element*, char*, int) (cli-decode.c:1913)
==21429== by 0x8DB790: execute_command(char*, int) (top.c:674)
==21429== by 0x632AE6: mi_execute_cli_command(char const*, int, char const*) (mi-main.c:2343)
==21429== by 0x6329BA: mi_cmd_execute(mi_parse*) (mi-main.c:2306)
==21429== by 0x631E19: captured_mi_execute_command(ui_out*, mi_parse*) (mi-main.c:1998)
==21429== by 0x632389: mi_execute_command(char const*, int) (mi-main.c:2163)
==21429==
[...]
==26635== 24 bytes in 1 blocks are definitely lost in loss record 20,740 of 34,995
==26635== at 0x4C29216: operator new(unsigned long) (vg_replace_malloc.c:334)
==26635== by 0x61C355: handle_redirections(int) (cli-logging.c:131)
==26635== by 0x61C6EC: set_logging_on(char*, int) (cli-logging.c:190)
==26635== by 0x6163BE: do_cfunc(cmd_list_element*, char*, int) (cli-decode.c:105)
==26635== by 0x6193C1: cmd_func(cmd_list_element*, char*, int) (cli-decode.c:1913)
==26635== by 0x8DB7BC: execute_command(char*, int) (top.c:674)
==26635== by 0x7B9132: command_handler(char*) (event-top.c:590)
==26635== by 0x7B94F7: command_line_handler(char*) (event-top.c:780)
==26635== by 0x7B8ABB: gdb_rl_callback_handler(char*) (event-top.c:213)
==26635== by 0x933CE9: rl_callback_read_char (callback.c:220)
==26635== by 0x7B89ED: gdb_rl_callback_read_char_wrapper_noexcept() (event-top.c:175)
==26635== by 0x7B8A49: gdb_rl_callback_read_char_wrapper(void*) (event-top.c:192)
One is fixed by transfering ownership of the log file to the tee. In
pseudo-patch, since the code was moved at the same time:
- out = new tee_file (curr_output, false, logfile.get (), false);
+ out = new tee_file (curr_output, false, logfile.get (), true);
The other is this bit in mi_set_logging:
else
{
+ delete mi->raw_stdout;
I tried to split the leak fixes to a smaller preparatory patch, but
that was difficult exactly because of the tee hack in
handle_redirections -> mi_set_logging.
gdb/ChangeLog:
2017-02-02 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (struct saved_output_files, saved_output):
Moved from cli/cli-logging.c.
(cli_set_logging): New function.
(cli_interp_procs): Install cli_set_logging.
* cli/cli-interp.h (make_logging_output, cli_set_logging):
Declare.
* cli/cli-logging.c (struct saved_output_files, saved_output):
Moved to cli/cli-interp.c.
(pop_output_files): Don't save outputs here.
(make_logging_output): New function.
(handle_redirections): Don't build tee nor save previous outputs
here.
* interps.c (current_interp_set_logging): Change prototype.
Assume there's always a set_logging_proc method installed.
* interps.h (interp_set_logging_ftype): Change prototype.
(current_interp_set_logging): Change prototype and adjust comment.
* mi/mi-interp.c (mi_set_logging): Change protototype. Adjust to
use make_logging_output.
* tui/tui-interp.c (tui_interp_procs): Install cli_set_logging.
2017-02-02 23:00:43 +01:00
|
|
|
disabled. LOGFILE is the stream for the log file when logging is
|
|
|
|
starting and is NULL when logging is ending. LOGGING_REDIRECT is
|
|
|
|
the value of the "set logging redirect" setting. If true, the
|
|
|
|
interpreter should configure the output streams to send output only
|
|
|
|
to the logfile. If false, the interpreter should configure the
|
|
|
|
output streams to send output to both the current output stream
|
|
|
|
(i.e., the terminal) and the log file. */
|
|
|
|
extern void current_interp_set_logging (ui_file_up logfile,
|
|
|
|
bool logging_redirect);
|
2012-06-29 00:11:23 +02:00
|
|
|
|
C++-fy struct interp/cli_interp/tui_interp/mi_interp
- The interp->data field disappears, since we can put data in the
interpreter directly now. The "init" method remains in place, but
it now returns void.
- A few places check if the interpreter method is NULL before calling
it, and also check whether the method returns true/false. For some
of those methods, all current implementations always return true.
In those cases, this commit makes the C++-fied method return void
instead and cleans up the callers.
Tested on x86_64 Fedora 23.
gdb/ChangeLog:
2017-02-03 Pedro Alves <palves@redhat.com>
* cli/cli-interp.c (cli_interp_base::cli_interp_base)
(cli_interp_base::~cli_interp_base): New.
(cli_interp): New struct.
(as_cli_interp): Cast the interp itself to cli_interp.
(cli_interpreter_pre_command_loop): Rename to ...
(cli_interp_base::pre_command_loop): ... this. Remove 'self'
parameter.
(cli_interpreter_init): Rename to ...
(cli_interp::init): ... this. Remove 'self' parameter. Use
boolean. Make extern.
(cli_interpreter_resume): Rename to ...
(cli_interp::resume): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_suspend): Rename to ...
(cli_interp::suspend): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_exec): Rename to ...
(cli_interp::exec): ... this. Remove 'data' parameter. Make
extern.
(cli_interpreter_supports_command_editing): Rename to ...
(cli_interp_base::supports_command_editing): ... this. Remove
'interp' parameter. Make extern.
(cli_ui_out): Rename to ...
(cli_interp::interp_ui_out): ... this. Remove 'interp' parameter.
Make extern.
(cli_set_logging): Rename to ...
(cli_interp_base::set_logging): ... this. Remove 'interp'
parameter. Make extern.
(cli_interp_procs): Delete.
(cli_interp_factory): Adjust to use "new".
* cli/cli-interp.h: Include "interps.h".
(struct cli_interp_base): New struct.
* interps.c (struct interp): Delete. Fields moved to interps.h.
(interp_new): Delete.
(interp::interp, interp::~interp): New.
(interp_set): Use bool, and return void. Assume the interpreter
has suspend, init and resume methods, and that the all return
void.
(set_top_level_interpreter): interp_set returns void.
(interp_ui_out): Adapt.
(current_interp_set_logging): Adapt.
(interp_data): Delete.
(interp_pre_command_loop, interp_supports_command_editing): Adapt.
(interp_exec): Adapt.
(top_level_interpreter_data): Delete.
* interps.h (interp_init_ftype, interp_resume_ftype)
(interp_suspend_ftype, interp_exec_ftype)
(interp_pre_command_loop_ftype, interp_ui_out_ftype): Delete.
(class interp): New.
(interp_new): Delete.
(interp_set): Now returns void. Use bool.
(interp_data, top_level_interpreter_data): Delete.
* mi/mi-common.h: Include interps.h.
(class mi_interp): Inherit from interp. Define a ctor. Declare
init, resume, suspect, exec, interp_ui_out, set_logging and
pre_command_loop methods.
* mi/mi-interp.c (as_mi_interp): Cast the interp itself.
(mi_interpreter_init): Rename to ...
(mi_interp::init): ... this. Remove the 'interp' parameter, use
bool, return void and make extern. Adjust.
(mi_interpreter_resume): ... Rename to ...
(mi_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_suspend): ... Rename to ...
(mi_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(mi_interpreter_exec): ... Rename to ...
(mi_interp::exec): ... this. Remove the 'data' parameter and make
extern. Adjust.
(mi_interpreter_pre_command_loop): ... Rename to ...
(mi_interp::pre_command_loop): ... this. Remove the 'self'
parameter and make extern.
(mi_on_normal_stop_1): Adjust.
(mi_ui_out): Rename to ...
(mi_interp::interp_ui_out): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_set_logging): Rename to ...
(mi_interp::set_logging): ... this. Remove the 'interp'
parameter and make extern. Adjust.
(mi_interp_procs): Delete.
(mi_interp_factory): Adjust to use 'new'.
* mi/mi-main.c (mi_cmd_gdb_exit, captured_mi_execute_command)
(mi_print_exception, mi_execute_command, mi_load_progress):
Adjust.
* tui/tui-interp.c (tui_interp): New class.
(as_tui_interp): Return a tui_interp pointer.
(tui_on_normal_stop, tui_on_signal_received)
(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
(tui_on_no_history, tui_on_user_selected_context_changed): Adjust
to use interp::interp_ui_out.
(tui_init): Rename to ...
(tui_interp::init): ... this. Remove the 'self' parameter, use
bool, return void and make extern. Adjust.
(tui_resume): Rename to ...
(tui_interp::resume): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_suspend): Rename to ...
(tui_interp::suspend): ... this. Remove the 'data' parameter,
return void and make extern. Adjust.
(tui_ui_out): Rename to ...
(tui_interp::interp_ui_out): ... this. Remove the 'self'
parameter, and make extern. Adjust.
(tui_exec): Rename to ...
(tui_interp::exec): ... this. Remove the 'data' parameter and
make extern.
(tui_interp_procs): Delete.
(tui_interp_factory): Use "new".
2017-02-03 17:30:04 +01:00
|
|
|
/* Returns the top-level interpreter. */
|
2008-04-19 08:09:15 +02:00
|
|
|
extern struct interp *top_level_interpreter (void);
|
2003-02-06 06:30:17 +01:00
|
|
|
|
2016-06-21 02:11:50 +02:00
|
|
|
/* Return the current UI's current interpreter. */
|
|
|
|
extern struct interp *current_interpreter (void);
|
|
|
|
|
PR gdb/13860: don't lose '-interpreter-exec console EXECUTION_COMMAND''s output in async mode.
The other part of PR gdb/13860 is about console execution commands in
MI getting their output half lost. E.g., take the finish command,
executed on a frontend's GDB console:
sync:
finish
&"finish\n"
~"Run till exit from #0 usleep (useconds=10) at ../sysdeps/unix/sysv/linux/usleep.c:27\n"
^running
*running,thread-id="1"
(gdb)
~"0x00000000004004d7 in foo () at stepinf.c:6\n"
~"6\t usleep (10);\n"
~"Value returned is $1 = 0\n"
*stopped,reason="function-finished",frame={addr="0x00000000004004d7",func="foo",args=[],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="6"},thread-id="1",stopped-threads="all",core="1"
async:
finish
&"finish\n"
~"Run till exit from #0 usleep (useconds=10) at ../sysdeps/unix/sysv/linux/usleep.c:27\n"
^running
*running,thread-id="1"
(gdb)
*stopped,reason="function-finished",frame={addr="0x00000000004004d7",func="foo",args=[],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="6"},gdb-result-var="$1",return-value="0",thread-id="1",stopped-threads="all",core="0"
Note how all the "Value returned" etc. output is missing in async mode.
The same happens with e.g., catchpoints:
=breakpoint-modified,bkpt={number="1",type="catchpoint",disp="keep",enabled="y",what="22016",times="1"}
~"\nCatchpoint "
~"1 (forked process 22016), 0x0000003791cbd8a6 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131\n"
~"131\t pid = ARCH_FORK ();\n"
*stopped,reason="fork",disp="keep",bkptno="1",newpid="22016",frame={addr="0x0000003791cbd8a6",func="__libc_fork",args=[],file="../nptl/sysdeps/unix/sysv/linux/fork.c",fullname="/usr/src/debug/glibc-2.14-394-g8f3b1ff/nptl/sysdeps/unix/sysv/linux/fork.c",line="131"},thread-id="1",stopped-threads="all",core="0"
where all those ~ lines are missing in async mode, or just the "step"
current line indication:
s
&"s\n"
^running
*running,thread-id="all"
(gdb)
~"13\t foo ();\n"
*stopped,frame={addr="0x00000000004004ef",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffdd78"}],file="stepinf.c",fullname="/home/pedro/gdb/tests/stepinf.c",line="13"},thread-id="1",stopped-threads="all",core="3"
(gdb)
Or in the case of the PRs example, the "Stopped due to shared library
event" note:
start
&"start\n"
~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
=thread-group-started,id="i1",pid="21990"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
~"Stopped due to shared library event (no libraries added or removed)\n"
*stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="3"
(gdb)
IMO, if you're typing execution commands in a frontend's console, you
expect to see their output. Indeed it's what you get in sync mode. I
think async mode should do the same. Deciding what to mirror to the
console wrt to breakpoints and random stops gets messy real fast.
E.g., say "s" trips on a breakpoint. We'd clearly want to mirror the
event to the console in this case. But what about more complicated
cases like "s&; thread n; s&", and one of those steps spawning a new
thread, and that thread hitting a breakpoint? It's impossible in
general to track whether the thread had any relation to the commands
that had been executed. So I think we should just simplify and always
mirror breakpoints and random events to the console.
Notes:
- mi->out is the same as gdb_stdout when MI is the current
interpreter. I think that referring to that directly is cleaner.
An earlier revision of this patch made the changes that are now
done in mi_on_normal_stop directly in infrun.c:normal_stop, and so
not having an obvious place to put the new uiout by then, and not
wanting to abuse CLI's uiout, I made a temporary uiout when
necessary.
- Hopefuly the rest of the patch is more or less obvious given the
comments added.
Tested on x86_64 Fedora 20, no regressions.
2014-05-21 Pedro Alves <palves@redhat.com>
PR gdb/13860
* gdbthread.h (struct thread_control_state): New field
`command_interp'.
* infrun.c (follow_fork): Copy the new thread control field to the
child fork thread.
(clear_proceed_status_thread): Clear the new thread control field.
(proceed): Set the new thread control field.
* interps.h (command_interp): Declare.
* interps.c (command_interpreter): New global.
(command_interp): New function.
(interp_exec): Set `command_interpreter' while here.
* cli-out.c (cli_uiout_dtor): New function.
(cli_ui_out_impl): Install it.
* mi/mi-interp.c: Include cli-out.h.
(mi_cmd_interpreter_exec): Add comment.
(restore_current_uiout_cleanup): New function.
(ui_out_free_cleanup): New function.
(mi_on_normal_stop): If finishing an execution command started by
a CLI command, or any kind of breakpoint-like event triggered,
print the stop event to the output (CLI) stream.
* mi/mi-out.c (mi_ui_out_impl): Install NULL `dtor' handler.
2014-05-21 Pedro Alves <palves@redhat.com>
PR gdb/13860
* gdb.mi/mi-cli.exp (line_callee4_next_step): New global.
(top level): Test that output related to execution commands is
sent to the console with CLI commands, but not with MI commands.
Test that breakpoint events are always mirrored to the console.
Also expect the new source line to be output after a "next" in
async mode too. Make it a pass/fail test.
* gdb.mi/mi-solib.exp: Test that the CLI solib event note is
output.
* lib/mi-support.exp (mi_gdb_expect_cli_output): New procedure.
2014-03-11 21:31:36 +01:00
|
|
|
extern struct interp *command_interp (void);
|
|
|
|
|
2003-06-08 Andrew Cagney <cagney@redhat.com>
* acinclude.m4 (gcc_AC_CHECK_DECL, (gcc_AC_CHECK_DECL): Stolen
from GCC's acinclude.m4.
* configure.in: Check for getopt's delcaration.
* aclocal.m4, config.in, configure: Re-generate.
* main.c (error_init): Delete declaration.
* defs.h (error_init): Declare.
* rs6000-tdep.c (rs6000_fetch_pointer_argument): Make static.
(rs6000_convert_from_func_ptr_addr): Make static.
(_initialize_rs6000_tdep): Add declaration.
* cli/cli-cmds.c (dont_repeat): Delete declaration.
(show_commands, set_verbose, show_history): Delete declaration.
* top.h (set_verbose): Add declaration.
(show_history, set_history, show_commands): Add declaration.
(do_restore_instream_cleanup): Add declaration.
* objc-lang.c (specialcmp): Make static.
(print_object_command): Make static.
(find_objc_msgsend): Make static.
(find_objc_msgcall_submethod_helper): Make static.
(find_objc_msgcall_submethod): Make static.
(_initialize_objc_language): Add declaration.
(find_implementation_from_class): Make static.
(find_implementation): Make static.
* objc-exp.y (yylex): Delete lookup_struct_typedef declaration.
* objc-lang.h (lookup_struct_typedef): Add declaration.
* cli/cli-interp.c (_initialize_cli_interp): Add declaration.
* cli/cli-script.c (clear_hook_in_cleanup): Make static.
(do_restore_user_call_depth): Make static.
(do_restore_instream_cleanup): Delete declaration.
(dont_repeat): Delete declaration.
* cli/cli-decode.c (add_abbrev_cmd): Delete function.
* cli/cli-dump.c (_initialize_cli_dump): Add declaration.
* reggroups.c (_initialize_reggroup): Add declaration.
* cp-support.c (_initialize_cp_support): Add declaration.
* cp-abi.c (_initialize_cp_abi): Add declaration.
* hpacc-abi.c (_initialize_hpacc_abi): Add declaration.
* gnu-v3-abi.c (gnuv3_baseclass_offset): Make static.
(_initialize_gnu_v3_abi): Add declaration.
* gnu-v2-abi.c (gnuv2_value_rtti_type): Make static.
(_initialize_gnu_v2_abi): Add declaration.
* frame-base.c (_initialize_frame_base): Add declaration.
* doublest.c (floatformat_from_length): Make static.
* frame-unwind.c (_initialize_frame_unwind): Add declaration.
* frame.c (create_sentinel_frame): Make static.
(_initialize_frame): Add declaration.
* top.c (do_catch_errors): Make static.
(gdb_rl_operate_and_get_next_completion): Make static.
* typeprint.c: Include "typeprint.h".
* sentinel-frame.c (sentinel_frame_prev_register): Make static.
(sentinel_frame_this_id): Make static.
* p-valprint.c (_initialize_pascal_valprint): Add declaration.
* ui-out.c (make_cleanup_ui_out_begin_end): Delete function.
* dwarf2-frame.c (dwarf2_frame_cache): Make static.
* p-exp.y (push_current_type, pop_current_type): ISO C declaration.
* dwarf2expr.h (dwarf_expr_context): ISO C declaration.
* maint.c (maintenance_print_architecture): Make static.
* signals/signals.c (_initialize_signals): Add declaration.
* std-regs.c (_initialize_frame_reg): Add declaration.
* jv-exp.y (push_variable): ISO C definition.
(push_qualified_expression_name): Ditto.
* memattr.c (_initialize_mem): Add declaration.
* remote.c (remote_check_watch_resources): Make static.
(remote_stopped_by_watchpoint): Make static.
(remote_stopped_data_address): Make static.
* d10v-tdep.c (nr_dmap_regs): Make static.
(a0_regnum): Make static.
(d10v_frame_unwind_cache): Make static.
(d10v_frame_p): Make static.
* osabi.c (show_osabi): Make static.
(_initialize_gdb_osabi): Add extern declaration.
* gdbtypes.c (make_qualified_type): Make static.
(safe_parse_type): Make static.
* macrocmd.c (_initialize_macrocmd): Add extern declaration.
* macrotab.c (macro_bcache_free): Make static.
* interps.c (interp_set_quiet): Make static.
(interpreter_exec_cmd): Make static.
* stack.h (select_frame_command): New file.
* stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete function.
(select_frame_command): Make global.
* infcall.c: Include "infcall.h".
* linespec.c: Include "linespec.h".
* symfile.c (sections_overlap): Make static.
* cp-support.h (cp_initialize_namespace): ISO C declaration.
* charset.c (_initialize_charset): Add missing prototype.
* regcache.c (init_legacy_regcache_descr): Make static.
(do_regcache_xfree): Make static.
(regcache_xfer_part): Make static.
(_initialize_regcache): Add missing prototype.
* breakpoint.c (parse_breakpoint_sals): Make static.
(breakpoint_sals_to_pc): Make static.
* interps.h (clear_interpreter_hooks): ISO C declaration.
* Makefile.in (stack_h): Define.
(stack.o, typeprint.o, mi-main.o): Update dependencies.
(mi-cmd-stack.o, infcall.o, linespec.o): Update dependencies.
Index: mi/ChangeLog
2003-06-08 Andrew Cagney <cagney@redhat.com>
* mi-parse.c (_initialize_mi_parse): Delete function.
* mi-main.c: Include "mi-main.h".
* mi-interp.c (_initialize_mi_interp): Add declaration.
* mi-cmd-stack.c: Include "stack.h".
(select_frame_command_wrapper): Delete extern declaration.
(mi_cmd_stack_select_frame): Replace select_frame_command_wrapper
with select_frame_command.
2003-06-08 20:27:14 +02:00
|
|
|
extern void clear_interpreter_hooks (void);
|
2003-02-06 06:30:17 +01:00
|
|
|
|
Make command line editing (use of readline) be per UI
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.
2016-06-21 02:11:48 +02:00
|
|
|
/* Returns true if INTERP supports using the readline library; false
|
|
|
|
if it uses GDB's own simplified form of readline. */
|
|
|
|
extern int interp_supports_command_editing (struct interp *interp);
|
|
|
|
|
2016-06-21 02:11:51 +02:00
|
|
|
/* Called before starting an event loop, to give the interpreter a
|
|
|
|
chance to e.g., print a prompt. */
|
|
|
|
extern void interp_pre_command_loop (struct interp *interp);
|
|
|
|
|
Add new command to create extra console/mi UIs
With all the previous plumbing in place, it's now easy to add a
command that actually creates a new console/mi UI.
The intended use case is to make it possible and easy for MI frontends
to provide a fully featured GDB console to users, with readline
support, command line editing, history, etc., just like if gdb was
started on the command line. Currently MI frontends have to try to
implement all of that theirselves and make use of "-interpreter-exec
console ...", which is far from perfect. If you ever tried Eclipse's
gdb console window, you'll know what I mean...
Instead of trying to multiplex console through MI, this command let's
just leverage all the built in readline/editing support already inside
gdb.
The plan is for the MI frontend to start GDB in regular console mode,
running inside a terminal emulator widget embedded in Eclipse (which
already exists, for supporting the shell widget; other frontends have
similar widgets), and then tell GDB to run a full MI interpreter on an
specified input/output device, independent of the console.
My original prototype planned to do things the other way around --
start GDB in MI mode, and then start an extra CLI console on separate
tty. I handed over that prototype to Marc Khouzam @ Eclipse CDT, and
after experimentation and discussion, we ended up concluding that
starting GDB in CLI mode instead was both easier and actually also
supported an interesting use case -- connect an Eclipse frontend to a
GDB that is already running outside Eclipse.
The current usage is "new-ui <interpreter> <tty>".
E.g., on a terminal run this scriplet:
$ cat gdb-client
#!/bin/bash
reset
tty
tail -f /dev/null
$ gdb-client
/dev/pts/15
Now run gdb on another terminal, and tell it to start a MI interpreter
on the tty of the other terminal:
...
(gdb) new-ui mi /dev/pts/15
New UI allocated
Now back to the the gdb-client terminal, we'll get an MI prompt, ready
for MI input:
/dev/pts/15
=thread-group-added,id="i1"
(gdb)
You can also start a new UI running a CLI, with:
(gdb) new-ui console /dev/pts/15
Though note that this console won't support readline command editing.
It works as if "set editing off" was entered.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* interps.c (set_top_level_interpreter): New function, factored
out from captured_main.
(interpreter_completer): Make extern.
* interps.h (set_top_level_interpreter, interpreter_completer):
New declarations.
(captured_main): Use set_top_level_interpreter.
* top.c [!O_NOCTTY] (O_NOCTTY): Define as 0.
(open_terminal_stream, new_ui_command): New functions.
(init_main): Install the "new-ui" command.
2016-06-21 02:11:55 +02:00
|
|
|
/* List the possible interpreters which could complete the given
|
|
|
|
text. */
|
Introduce class completion_tracker & rewrite completion<->readline interaction
This patch reworks the whole completion machinery, and prepares it
for later enhancements.
Adds a new "completion_tracker" class that is meant to hold everything
about the state of the current completion operation.
This class now has the responsibility of tracking the list of
completion matches, and checking whether the max completions limit has
been reached. You can look at this as this patch starting out by
C++fying the existing "completion_tracker" in symtab.c (it's just an
htab_t typedef currently), moving it to completer.h/c, and then making
it a class/generalizing/enhancing it.
Unlike with the current tracking, completion_tracker now checks
whether the limit has been reached on each completion match list
insertion. This both simplifies the max-completions handling code
(maybe_add_completion_enum is gone, for example), and is a
prerequisite for follow up patches.
The current completion_tracker is only used for symbol completions,
and the symbol code gets at the current instance via globals. This
patch cleans that up by adding a completion_tracker reference to the
signature of the completion functions, and passing the tracker around
everywhere necessary.
Then, the patch changes how the completion match list is handed over
to readline. Currently, we're using the rl_completion_entry_function
readline entry point, and the patch switches to
rl_attempted_completion_function. A following patch will want to let
GDB itself decide the common completion prefix between all matches
(what readline calls the "lowest common denominator"), instead of
having readline compute it, and that's not possible with the
rl_completion_entry_function entry point. Also,
rl_attempted_completion_function lets GDB hand over the match list to
readline as an array in one go instead of passing down matches one by
one, so from that angle it's a nicer entry point anyway.
Lastly, the patch catches exceptions around the readline entry points,
because we can't let C++ exceptions cross readline. We handle that in
the readline input entry point, but the completion entry point isn't
guarded, so GDB can abort if completion throws. E.g., in current
master:
(gdb) b -function "fun<tab>
terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'
Aborted (core dumped)
This patch fixes that. This will be exercised in the new tests added
later on in the series.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (symbol_completion_match): Adjust comments.
(symbol_completion_add): Replace vector parameter with
completion_tracker parameter. Use it.
(ada_make_symbol_completion_list): Rename to...
(ada_collect_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it.
(ada_language_defn): Adjust.
* break-catch-syscall.c (catch_syscall_completer): Adjust
prototype and work with completion_tracker instead of VEC.
* breakpoint.c (condition_completer): Adjust prototype and work
with completion_tracker instead of VEC.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Adjust to renames.
* cli/cli-cmds.c (complete_command): Rework using
completion_tracker. Catch exceptions when completing.
* cli/cli-decode.c (integer_unlimited_completer)
(complete_on_cmdlist, complete_on_enum): Adjust prototype and work
with completion_tracker instead of VEC.
* command.h (struct completion_tracker): Forward declare.
(completer_ftype, completer_handle_brkchars_ftype): Change
types.
(complete_on_cmdlist, complete_on_enum): Adjust.
* completer.c: Include <algorithm>.
(struct gdb_completer_state): New.
(current_completion): New global.
(readline_line_completion_function): Delete.
(noop_completer, filename_completer)
(filename_completer_handle_brkchars, complete_files_symbols)
(linespec_location_completer): Adjust to work with a
completion_tracker instead of a VEC.
(string_or_empty): New.
(collect_explicit_location_matches): Adjust to work with a
completion_tracker instead of a VEC.
(explicit_location_completer): Rename to ...
(complete_explicit_location): ... this and adjust to work with a
completion_tracker instead of a VEC.
(location_completer): Adjust to work with a completion_tracker
instead of a VEC.
(add_struct_fields): Adjust to work with a completion_list instead
of VEC.
(expression_completer): Rename to ...
(complete_expression): ... this and adjust to work with a
completion_tracker instead of a VEC. Use complete_files_symbols.
(expression_completer): Reimplement on top of complete_expression.
(symbol_completer): Adjust to work with a completion_tracker
instead of a VEC.
(enum complete_line_internal_reason): Add describing comments.
(complete_line_internal_normal_command): Adjust to work with a
completion_tracker instead of a VEC.
(complete_line_internal): Rename to ...
(complete_line_internal_1): ... this and adjust to work with a
completion_tracker instead of a VEC. Assert TEXT is NULL in the
handle_brkchars phase.
(new_completion_tracker): Delete.
(complete_line_internal): Reimplement as TRY/CATCH wrapper around
complete_line_internal_1.
(free_completion_tracker): Delete.
(INITIAL_COMPLETION_HTAB_SIZE): New.
(completion_tracker::completion_tracker)
(completion_tracker::~completion_tracker): New.
(maybe_add_completion): Delete.
(completion_tracker::maybe_add_completion)
(completion_tracker::add_completion)
(completion_tracker::add_completions): New.
(throw_max_completions_reached_error): Delete.
(complete_line): Adjust to work with a completion_tracker instead
of a VEC. Don't create a completion_tracker_t or check for max
completions here.
(command_completer, command_completer_handle_brkchars)
(signal_completer, reg_or_group_completer_1)
(reg_or_group_completer, default_completer_handle_brkchars):
Adjust to work with a completion_tracker.
(gdb_completion_word_break_characters_throw): New.
(gdb_completion_word_break_characters): Reimplement.
(line_completion_function): Delete.
(completion_tracker::recompute_lowest_common_denominator)
(expand_preserving_ws)
(completion_tracker::build_completion_result)
(completion_result::completion_result)
(completion_result::completion_result)
(completion_result::~completion_result)
(completion_result::completion_result)
(completion_result::release_match_list, compare_cstrings)
(completion_result::sort_match_list)
(completion_result::reset_match_list)
(gdb_rl_attempted_completion_function_throw)
(gdb_rl_attempted_completion_function): New.
* completer.h (completion_list, struct completion_result)
(class completion_tracker): New.
(complete_line): Add completion_tracker parameter.
(readline_line_completion_function): Delete.
(gdb_rl_attempted_completion_function): New.
(noop_completer, filename_completer, expression_completer)
(location_completer, symbol_completer, command_completer)
(signal_completer, reg_or_group_completer): Update prototypes.
(completion_tracker_t, new_completion_tracker)
(make_cleanup_free_completion_tracker): Delete.
(enum maybe_add_completion_enum): Delete.
(maybe_add_completion): Delete.
(throw_max_completions_reached_error): Delete.
* corefile.c (complete_set_gnutarget): Adjust to work with a
completion_tracker instead of a VEC.
* cp-abi.c (cp_abi_completer): Adjust to work with a
completion_tracker instead of a VEC.
* d-lang.c (d_language_defn): Adjust.
* disasm.c (disassembler_options_completer): Adjust to work with a
completion_tracker instead of a VEC.
* f-lang.c (f_make_symbol_completion_list): Rename to ...
(f_collect_symbol_completion_matches): ... this. Adjust to work
with a completion_tracker instead of a VEC.
(f_language_defn): Adjust.
* go-lang.c (go_language_defn): Adjust.
* guile/scm-cmd.c (cmdscm_add_completion, cmdscm_completer):
Adjust to work with a completion_tracker instead of a VEC.
* infrun.c (handle_completer): Likewise.
* interps.c (interpreter_completer): Likewise.
* interps.h (interpreter_completer): Likewise.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Adjust.
* language.h (language_defn::la_make_symbol_completion_list):
Rename to ...
(language_defn::la_collect_symbol_completion_matches): ... this
and adjust to work with a completion_tracker instead of a VEC.
* m2-lang.c (m2_language_defn): Adjust.
* objc-lang.c (objc_language_defn): Adjust.
* opencl-lang.c (opencl_language_defn): Adjust.
* p-lang.c (pascal_language_defn): Adjust.
* python/py-cmd.c (cmdpy_completer_helper): Handle NULL word.
(cmdpy_completer_handle_brkchars, cmdpy_completer): Adjust to work
with a completion_tracker.
* rust-lang.c (rust_language_defn): Adjust.
* symtab.c (free_completion_list, do_free_completion_list)
(return_val, completion_tracker): Delete.
(completion_list_add_name, completion_list_add_symbol)
(completion_list_add_msymbol, completion_list_objc_symbol)
(completion_list_add_fields, add_symtab_completions): Add
completion_tracker parameter and use it.
(default_make_symbol_completion_list_break_on_1): Rename to...
(default_collect_symbol_completion_matches_break_on): ... this.
Add completion_tracker parameter and use it instead of allocating
a completion tracker here.
(default_make_symbol_completion_list_break_on): Delete old
implementation.
(default_make_symbol_completion_list): Delete.
(default_collect_symbol_completion_matches): New.
(make_symbol_completion_list): Delete.
(collect_symbol_completion_matches): New.
(make_symbol_completion_type): Rename to ...
(collect_symbol_completion_matches_type): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list_1): Rename to...
(collect_file_symbol_completion_matches): ... this. Add
completion_tracker parameter and use it instead of VEC.
(make_file_symbol_completion_list): Delete.
(add_filename_to_list): Use completion_list instead of a VEC.
(add_partial_filename_data::list): Now a completion_list.
(make_source_files_completion_list): Work with a completion_list
instead of a VEC.
* symtab.h: Include "completer.h".
(default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list, make_symbol_completion_list)
(make_symbol_completion_type, make_file_symbol_completion_list)
(make_source_files_completion_list): Delete.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_symbol_completion_matches_type)
(collect_file_symbol_completion_matches)
(make_source_files_completion_list): New.
* top.c (init_main): Don't install a rl_completion_entry_function
hook. Install a rl_attempted_completion_function hook instead.
* tui/tui-layout.c (layout_completer): Adjust to work with a
completion_tracker.
* tui/tui-regs.c (tui_reggroup_completer):
* tui/tui-win.c (window_name_completer, focus_completer)
(winheight_completer): Adjust to work with a completion_tracker.
* value.c: Include "completer.h".
(complete_internalvar): Adjust to work with a completion_tracker.
* value.h (complete_internalvar): Likewise.
2017-07-17 15:45:59 +02:00
|
|
|
extern void interpreter_completer (struct cmd_list_element *ignore,
|
|
|
|
completion_tracker &tracker,
|
|
|
|
const char *text,
|
|
|
|
const char *word);
|
Add new command to create extra console/mi UIs
With all the previous plumbing in place, it's now easy to add a
command that actually creates a new console/mi UI.
The intended use case is to make it possible and easy for MI frontends
to provide a fully featured GDB console to users, with readline
support, command line editing, history, etc., just like if gdb was
started on the command line. Currently MI frontends have to try to
implement all of that theirselves and make use of "-interpreter-exec
console ...", which is far from perfect. If you ever tried Eclipse's
gdb console window, you'll know what I mean...
Instead of trying to multiplex console through MI, this command let's
just leverage all the built in readline/editing support already inside
gdb.
The plan is for the MI frontend to start GDB in regular console mode,
running inside a terminal emulator widget embedded in Eclipse (which
already exists, for supporting the shell widget; other frontends have
similar widgets), and then tell GDB to run a full MI interpreter on an
specified input/output device, independent of the console.
My original prototype planned to do things the other way around --
start GDB in MI mode, and then start an extra CLI console on separate
tty. I handed over that prototype to Marc Khouzam @ Eclipse CDT, and
after experimentation and discussion, we ended up concluding that
starting GDB in CLI mode instead was both easier and actually also
supported an interesting use case -- connect an Eclipse frontend to a
GDB that is already running outside Eclipse.
The current usage is "new-ui <interpreter> <tty>".
E.g., on a terminal run this scriplet:
$ cat gdb-client
#!/bin/bash
reset
tty
tail -f /dev/null
$ gdb-client
/dev/pts/15
Now run gdb on another terminal, and tell it to start a MI interpreter
on the tty of the other terminal:
...
(gdb) new-ui mi /dev/pts/15
New UI allocated
Now back to the the gdb-client terminal, we'll get an MI prompt, ready
for MI input:
/dev/pts/15
=thread-group-added,id="i1"
(gdb)
You can also start a new UI running a CLI, with:
(gdb) new-ui console /dev/pts/15
Though note that this console won't support readline command editing.
It works as if "set editing off" was entered.
gdb/ChangeLog:
2016-06-21 Pedro Alves <palves@redhat.com>
* interps.c (set_top_level_interpreter): New function, factored
out from captured_main.
(interpreter_completer): Make extern.
* interps.h (set_top_level_interpreter, interpreter_completer):
New declarations.
(captured_main): Use set_top_level_interpreter.
* top.c [!O_NOCTTY] (O_NOCTTY): Define as 0.
(open_terminal_stream, new_ui_command): New functions.
(init_main): Install the "new-ui" command.
2016-06-21 02:11:55 +02:00
|
|
|
|
2003-02-06 06:30:17 +01:00
|
|
|
/* well-known interpreters */
|
|
|
|
#define INTERP_CONSOLE "console"
|
|
|
|
#define INTERP_MI1 "mi1"
|
Index: ChangeLog
2003-08-07 Andrew Cagney <cagney@redhat.com>
* interps.h (INTERP_MI2, INTERP_MI3): Define.
Index: doc/ChangeLog
2003-08-07 Andrew Cagney <cagney@redhat.com>
* gdb.texinfo (Mode Options): Mention that "mi2" was included in
GDB 6.0.
Index: mi/ChangeLog
2003-08-07 Andrew Cagney <cagney@redhat.com>
* mi-interp.c (_initialize_mi_interp): Register "mi2" and "mi3".
Make "mi" select "mi2".
Index: testsuite/gdb.mi/ChangeLog
2003-08-07 Andrew Cagney <cagney@redhat.com>
* mi2-basics.exp: Copy base MI .exp file, set MIFLAGS to -i=mi2.
* mi2-break.exp, mi2-cli.exp, mi2-console.exp: Ditto.
* mi2-disassemble.exp, mi2-eval.exp, mi2-file.exp: Ditto.
* mi2-hack-cli.exp, mi2-pthreads.exp, mi2-read-memory.exp: Ditto.
* mi2-regs.exp, mi2-return.exp, mi2-simplerun.exp: Ditto.
* mi2-stack.exp, mi2-stepi.exp, mi2-syn-frame.exp: Ditto.
* mi2-until.exp, mi2-var-block.exp, mi2-var-child.exp: Ditto.
* mi2-var-cmd.exp, mi2-var-display.exp, mi2-watch.exp: Ditto.
2003-08-07 19:47:42 +02:00
|
|
|
#define INTERP_MI2 "mi2"
|
|
|
|
#define INTERP_MI3 "mi3"
|
2003-02-06 06:30:17 +01:00
|
|
|
#define INTERP_MI "mi"
|
2004-02-18 20:01:36 +01:00
|
|
|
#define INTERP_TUI "tui"
|
2005-11-07 13:46:38 +01:00
|
|
|
#define INTERP_INSIGHT "insight"
|
2003-02-06 06:30:17 +01:00
|
|
|
|
|
|
|
#endif
|