Introduce "struct ui"

This is a step towards supporting multiple consoles/MIs, each on its
own stdio streams / terminal.

See intro comment in top.h.

(I've had trouble picking a name for this object.  I've started out
with "struct console" originally.  But then this is about MI as well,
and there's "interpreter-exec console", which is specifically about
the CLI...

So I changed to "struct terminal", but, then we have a terminal object
that works when the input is not a terminal as well ...

Then I sort of gave up and renamed it to "struct top_level".  But it
then gets horribly confusing when we talk about the "top level
interpreter that's running on the current top level".

In the end, I realized we're already sort of calling this "ui", in
struct ui_out, struct ui_file, and a few coments here and there.)

gdb/ChangeLog:
2016-06-21  Pedro Alves  <palves@redhat.com>

	* event-top.c: Update readline-related comments.
	(input_handler, call_readline): Delete globals.
	(gdb_rl_callback_handler): Call the current UI's input_handler
	method.
	(change_line_handler): Adjust to set current UI's properties
	instead of globals.
	(current_ui_, current_ui): New globals.
	(get_command_line_buffer): Rewrite to refer to the current UI.
	(stdin_event_handler): Adjust to call the call_readline method of
	the current UI.
	(gdb_readline_no_editing_callback): Adjust to call the current UI's
	input_handler method.
	(gdb_setup_readline): Adjust to set current UI's properties
	instead of globals.
	* event-top.h (call_readline, input_handler): Delete declarations.
	* mi/mi-interp.c (mi_interpreter_resume): Adjust to set current
	UI's properties instead of globals.
	* top.c (gdb_readline_wrapper_cleanup): Adjust to set current UI's
	properties instead of globals.
	(gdb_readline_wrapper): Adjust to call and set current UI's
	methods instead of globals.
	* top.h: Include buffer.h and event-loop.h.
	(struct ui): New struct.
	(current_ui): New declaration.
This commit is contained in:
Pedro Alves 2016-06-21 01:11:44 +01:00
parent 45db7c09c3
commit a74e1786ac
6 changed files with 97 additions and 54 deletions

View File

@ -1,3 +1,30 @@
2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c: Update readline-related comments.
(input_handler, call_readline): Delete globals.
(gdb_rl_callback_handler): Call the current UI's input_handler
method.
(change_line_handler): Adjust to set current UI's properties
instead of globals.
(current_ui_, current_ui): New globals.
(get_command_line_buffer): Rewrite to refer to the current UI.
(stdin_event_handler): Adjust to call the call_readline method of
the current UI.
(gdb_readline_no_editing_callback): Adjust to call the current UI's
input_handler method.
(gdb_setup_readline): Adjust to set current UI's properties
instead of globals.
* event-top.h (call_readline, input_handler): Delete declarations.
* mi/mi-interp.c (mi_interpreter_resume): Adjust to set current
UI's properties instead of globals.
* top.c (gdb_readline_wrapper_cleanup): Adjust to set current UI's
properties instead of globals.
(gdb_readline_wrapper): Adjust to call and set current UI's
methods instead of globals.
* top.h: Include buffer.h and event-loop.h.
(struct ui): New struct.
(current_ui): New declaration.
2016-06-21 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_exception_name_addr_1): Add comment.

View File

@ -75,28 +75,10 @@ static void async_stop_sig (gdb_client_data);
#endif
static void async_sigterm_handler (gdb_client_data arg);
/* Readline offers an alternate interface, via callback
functions. These are all included in the file callback.c in the
readline distribution. This file provides (mainly) a function, which
the event loop uses as callback (i.e. event handler) whenever an event
is detected on the standard input file descriptor.
readline_callback_read_char is called (by the GDB event loop) whenever
there is a new character ready on the input stream. This function
incrementally builds a buffer internal to readline where it
accumulates the line read up to the point of invocation. In the
special case in which the character read is newline, the function
invokes a GDB supplied callback routine, which does the processing of
a full command line. This latter routine is the asynchronous analog
of the old command_line_input in gdb. Instead of invoking (and waiting
for) readline to read the command line and pass it back to
command_loop for processing, the new command_line_handler function has
the command line already available as its parameter. INPUT_HANDLER is
to be set to the function that readline will invoke when a complete
line of input is ready. CALL_READLINE is to be set to the function
that readline offers as callback to the event_loop. */
void (*input_handler) (char *);
void (*call_readline) (gdb_client_data);
/* Instead of invoking (and waiting for) readline to read the command
line and pass it back for processing, we use readline's alternate
interface, via callback functions, so that the event loop can react
to other event sources while we wait for input. */
/* Important variables for the event loop. */
@ -217,10 +199,11 @@ static void
gdb_rl_callback_handler (char *rl)
{
struct gdb_exception gdb_rl_expt = exception_none;
struct ui *ui = current_ui;
TRY
{
input_handler (rl);
ui->input_handler (rl);
}
CATCH (ex, RETURN_MASK_ALL)
{
@ -261,6 +244,8 @@ cli_command_loop (void *data)
static void
change_line_handler (void)
{
struct ui *ui = current_ui;
/* NOTE: this operates on input_fd, not instream. If we are reading
commands from a file, instream will point to the file. However in
async mode, we always read commands from a file with editing
@ -270,18 +255,18 @@ change_line_handler (void)
if (async_command_editing_p)
{
/* Turn on editing by using readline. */
call_readline = gdb_rl_callback_read_char_wrapper;
input_handler = command_line_handler;
ui->call_readline = gdb_rl_callback_read_char_wrapper;
ui->input_handler = command_line_handler;
}
else
{
/* Turn off editing by using gdb_readline_no_editing_callback. */
gdb_rl_callback_handler_remove ();
call_readline = gdb_readline_no_editing_callback;
ui->call_readline = gdb_readline_no_editing_callback;
/* Set up the command handler as well, in case we are called as
first thing from .gdbinit. */
input_handler = command_line_handler;
ui->input_handler = command_line_handler;
}
}
@ -452,22 +437,16 @@ top_level_prompt (void)
return xstrdup (prompt);
}
/* Get a pointer to the command line buffer. This is used to
static struct ui current_ui_;
struct ui *current_ui = &current_ui_;
/* Get a pointer to the current UI's line buffer. This is used to
construct a whole line of input from partial input. */
static struct buffer *
get_command_line_buffer (void)
{
static struct buffer line_buffer;
static int line_buffer_initialized;
if (!line_buffer_initialized)
{
buffer_init (&line_buffer);
line_buffer_initialized = 1;
}
return &line_buffer;
return &current_ui->line_buffer;
}
/* When there is an event ready on the stdin file descriptor, instead
@ -478,6 +457,8 @@ get_command_line_buffer (void)
void
stdin_event_handler (int error, gdb_client_data client_data)
{
struct ui *ui = current_ui;
if (error)
{
printf_unfiltered (_("error detected on stdin\n"));
@ -499,7 +480,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
do
{
call_stdin_event_handler_again_p = 0;
(*call_readline) (client_data);
ui->call_readline (client_data);
} while (call_stdin_event_handler_again_p != 0);
}
}
@ -756,6 +737,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
char *result;
struct buffer line_buffer;
static int done_once = 0;
struct ui *ui = current_ui;
buffer_init (&line_buffer);
@ -795,7 +777,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
break;
}
xfree (buffer_finish (&line_buffer));
(*input_handler) (0);
ui->input_handler (NULL);
return;
}
@ -812,7 +794,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
buffer_grow_char (&line_buffer, '\0');
result = buffer_finish (&line_buffer);
(*input_handler) (result);
ui->input_handler (result);
}
@ -1198,6 +1180,8 @@ set_async_editing_command (char *args, int from_tty,
void
gdb_setup_readline (void)
{
struct ui *ui = current_ui;
/* This function is a noop for the sync case. The assumption is
that the sync setup is ALL done in gdb_init, and we would only
mess it up here. The sync stuff should really go away over
@ -1220,19 +1204,19 @@ gdb_setup_readline (void)
/* When a character is detected on instream by select or poll,
readline will be invoked via this callback function. */
call_readline = gdb_rl_callback_read_char_wrapper;
ui->call_readline = gdb_rl_callback_read_char_wrapper;
}
else
{
async_command_editing_p = 0;
call_readline = gdb_readline_no_editing_callback;
ui->call_readline = gdb_readline_no_editing_callback;
}
/* When readline has read an end-of-line character, it passes the
complete line to gdb for processing; command_line_handler is the
function that does this. */
input_handler = command_line_handler;
ui->input_handler = command_line_handler;
/* Tell readline to use the same input stream that gdb uses. */
rl_instream = instream;

View File

@ -57,8 +57,6 @@ extern void async_enable_stdin (void);
extern int async_command_editing_p;
extern int exec_done_display_p;
extern struct prompts the_prompts;
extern void (*call_readline) (void *);
extern void (*input_handler) (char *);
extern int input_fd;
extern void (*after_char_processing_hook) (void);
extern int call_stdin_event_handler_again_p;

View File

@ -175,6 +175,7 @@ static int
mi_interpreter_resume (void *data)
{
struct mi_interp *mi = (struct mi_interp *) data;
struct ui *ui = current_ui;
/* As per hack note in mi_interpreter_init, swap in the output
channels... */
@ -182,8 +183,8 @@ mi_interpreter_resume (void *data)
/* These overwrite some of the initialization done in
_intialize_event_loop. */
call_readline = gdb_readline_no_editing_callback;
input_handler = mi_execute_command_input_handler;
ui->call_readline = gdb_readline_no_editing_callback;
ui->input_handler = mi_execute_command_input_handler;
async_command_editing_p = 0;
/* FIXME: This is a total hack for now. PB's use of the MI
implicitly relies on a bug in the async support which allows

View File

@ -794,13 +794,14 @@ struct gdb_readline_wrapper_cleanup
static void
gdb_readline_wrapper_cleanup (void *arg)
{
struct ui *ui = current_ui;
struct gdb_readline_wrapper_cleanup *cleanup
= (struct gdb_readline_wrapper_cleanup *) arg;
rl_already_prompted = cleanup->already_prompted_orig;
gdb_assert (input_handler == gdb_readline_wrapper_line);
input_handler = cleanup->handler_orig;
gdb_assert (ui->input_handler == gdb_readline_wrapper_line);
ui->input_handler = cleanup->handler_orig;
/* Don't restore our input handler in readline yet. That would make
readline prep the terminal (putting it in raw mode), while the
@ -826,13 +827,14 @@ gdb_readline_wrapper_cleanup (void *arg)
char *
gdb_readline_wrapper (const char *prompt)
{
struct ui *ui = current_ui;
struct cleanup *back_to;
struct gdb_readline_wrapper_cleanup *cleanup;
char *retval;
cleanup = XNEW (struct gdb_readline_wrapper_cleanup);
cleanup->handler_orig = input_handler;
input_handler = gdb_readline_wrapper_line;
cleanup->handler_orig = ui->input_handler;
ui->input_handler = gdb_readline_wrapper_line;
cleanup->already_prompted_orig = rl_already_prompted;

View File

@ -20,7 +20,38 @@
#ifndef TOP_H
#define TOP_H
struct buffer;
#include "buffer.h"
#include "event-loop.h"
/* All about a user interface instance. Each user interface has its
own I/O files/streams, readline state, its own top level
interpreter (for the main UI, this is the interpreter specified
with -i on the command line) and secondary interpreters (for
interpreter-exec ...), etc. There's always one UI associated with
stdin/stdout/stderr, but the user can create secondary UIs, for
example, to create a separate MI channel on its own stdio
streams. */
struct ui
{
/* The UI's command line buffer. This is to used to accumulate
input until we have a whole command line. */
struct buffer line_buffer;
/* The callback used by the event loop whenever an event is detected
on the UI's input file descriptor. This function incrementally
builds a buffer where it accumulates the line read up to the
point of invocation. In the special case in which the character
read is newline, the function invokes the INPUT_HANDLER callback
(see below). */
void (*call_readline) (gdb_client_data);
/* The function to invoke when a complete line of input is ready for
processing. */
void (*input_handler) (char *);
};
extern struct ui *current_ui;
/* From top.c. */
extern char *saved_command_line;