Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: gdb-patches@sourceware.org
Subject: [PATCH v3 03/34] Introduce "struct ui"
Date: Fri, 06 May 2016 12:35:00 -0000	[thread overview]
Message-ID: <1462538104-19109-4-git-send-email-palves@redhat.com> (raw)
In-Reply-To: <1462538104-19109-1-git-send-email-palves@redhat.com>

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:
yyyy-mm-dd  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.
---
 gdb/event-top.c    | 74 +++++++++++++++++++++---------------------------------
 gdb/event-top.h    |  2 --
 gdb/mi/mi-interp.c |  5 ++--
 gdb/top.c          | 10 +++++---
 gdb/top.h          | 33 +++++++++++++++++++++++-
 5 files changed, 70 insertions(+), 54 deletions(-)

diff --git a/gdb/event-top.c b/gdb/event-top.c
index f43fd0a..664543c 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -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);
 }
 \f
 
@@ -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;
 
diff --git a/gdb/event-top.h b/gdb/event-top.h
index bef2530..04956a5 100644
--- a/gdb/event-top.h
+++ b/gdb/event-top.h
@@ -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;
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index b37dc96..7c82950 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -174,6 +174,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... */
@@ -181,8 +182,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
diff --git a/gdb/top.c b/gdb/top.c
index f5ef718..cae90d6 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -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;
 
diff --git a/gdb/top.h b/gdb/top.h
index a498f39..fc4e90a 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -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;
-- 
2.5.5


  parent reply	other threads:[~2016-05-06 12:35 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-06 12:35 [PATCH v3 00/34] Towards great frontend GDB consoles Pedro Alves
2016-05-06 12:35 ` [PATCH v3 24/34] Push thread->control.command_interp to the struct thread_fsm Pedro Alves
2016-07-01 11:02   ` Thomas Preudhomme
     [not found]     ` <20144b4c-11ee-fc84-e3ad-b9992f14ce15@redhat.com>
2016-07-01 15:24       ` [PATCH] Build gdb.opt/inline-*.exp tests at -O0, rely on __attribute__((always_inline)) (was: Re: [PATCH v3 24/34] Push thread->control.command_interp to the struct thread_fsm) Thomas Preudhomme
2016-07-15 12:05         ` Thomas Preudhomme
2016-07-19 17:02           ` [PATCH] Build gdb.opt/inline-*.exp tests at -O0, rely on __attribute__((always_inline)) Pedro Alves
2016-07-20 16:35             ` Thomas Preudhomme
2016-05-06 12:35 ` [PATCH v3 29/34] Add new command to create extra console/mi UI channels Pedro Alves
2016-05-26 18:34   ` Pedro Alves
2016-05-06 12:35 ` Pedro Alves [this message]
2016-05-06 12:35 ` [PATCH v3 16/34] Make target_terminal_inferior/ours almost nops on non-main UIs Pedro Alves
2016-05-06 12:35 ` [PATCH v3 15/34] Always process target events in the main UI Pedro Alves
2016-05-06 12:35 ` [PATCH v3 01/34] Prepare gdb.python/mi-py-events.exp for Python/MI in separate channels Pedro Alves
2016-05-06 12:35 ` [PATCH v3 14/34] Make command line editing (use of readline) be per UI Pedro Alves
2016-05-06 12:35 ` [PATCH v3 21/34] Replace the sync_execution global with a new enum prompt_state tristate Pedro Alves
2016-05-06 12:35 ` [PATCH v3 20/34] Make gdb_in_secondary_prompt_p() be per UI Pedro Alves
2016-05-06 12:35 ` [PATCH v3 33/34] Make mi-break.exp always expect breakpoint commands output on the main UI Pedro Alves
2016-05-06 12:35 ` [PATCH v3 02/34] [Ada catchpoints] Fix "warning: failed to get exception name: No definition of \"e.full_name\" in current context" Pedro Alves
2016-05-06 12:36 ` [PATCH v3 31/34] Add testing infrastruture bits for running with MI on a separate UI Pedro Alves
2016-06-28 20:19   ` Simon Marchi
2016-06-29 10:50     ` Pedro Alves
2016-06-30 11:12       ` [pushed] Fix gdbserver/MI testing regression (was: Re: [PATCH v3 31/34] Add testing infrastruture bits for running with MI on a separate UI) Pedro Alves
2016-06-30 12:10         ` gdbserver/ada testing broken (was: Re: [pushed] Fix gdbserver/MI testing regression) Pedro Alves
2016-07-04 20:40           ` gdbserver/ada testing broken Simon Marchi
2016-07-05 15:28             ` Joel Brobecker
2016-07-05 15:47               ` Joel Brobecker
2016-07-05 16:36           ` gdbserver/ada testing broken (was: Re: [pushed] Fix gdbserver/MI testing regression) Joel Brobecker
2016-07-05 17:19             ` gdbserver/ada testing broken Simon Marchi
2016-07-06 13:23               ` Joel Brobecker
2016-07-06 14:28                 ` Simon Marchi
2016-07-19 17:11               ` Pedro Alves
2016-07-04 17:22         ` [pushed] Fix gdbserver/MI testing regression Simon Marchi
2016-05-06 12:40 ` [PATCH v3 11/34] Make out and error streams be per UI Pedro Alves
2016-05-06 12:40 ` [PATCH v3 13/34] Make current_ui_out " Pedro Alves
2016-05-06 12:40 ` [PATCH v3 23/34] New function should_print_stop_to_console Pedro Alves
2016-05-06 12:41 ` [PATCH v3 06/34] Introduce interpreter factories Pedro Alves
2016-05-18 19:18   ` Simon Marchi
2016-05-26 18:11     ` Pedro Alves
2016-05-18 19:20   ` Simon Marchi
2016-05-26 18:08     ` Pedro Alves
2016-05-06 12:42 ` [PATCH v3 30/34] [DOC] Document support for running interpreters on separate UI channels Pedro Alves
2016-05-06 13:04   ` Eli Zaretskii
2016-05-26 11:11     ` Pedro Alves
2016-06-17 17:24       ` Pedro Alves
2016-06-17 20:02         ` Eli Zaretskii
2016-05-06 12:43 ` [PATCH v3 12/34] Delete def_uiout Pedro Alves
2016-05-06 12:43 ` [PATCH v3 04/34] Make gdb_stdout&co be per UI Pedro Alves
2016-05-06 12:43 ` [PATCH v3 17/34] Introduce display_mi_prompt Pedro Alves
2016-05-06 12:43 ` [PATCH v3 05/34] Make the interpreters be per UI Pedro Alves
2016-05-18 17:51   ` Simon Marchi
2016-05-26 18:08     ` Pedro Alves
2016-05-06 12:43 ` [PATCH v3 10/34] Make input_fd " Pedro Alves
2016-05-06 12:43 ` [PATCH v3 07/34] Make the intepreters output to all UIs Pedro Alves
2016-05-19 15:16   ` Simon Marchi
2016-05-26 18:12     ` Pedro Alves
2016-05-06 12:43 ` [PATCH v3 25/34] Only send sync execution command output to the UI that ran the command Pedro Alves
2016-05-06 12:43 ` [PATCH v3 08/34] Always run async signal handlers in the main UI Pedro Alves
2016-05-19 19:28   ` Simon Marchi
2016-05-26 18:13     ` Pedro Alves
2016-05-26 18:15       ` Simon Marchi
2016-05-06 12:43 ` [PATCH v3 28/34] Make stdin be per UI Pedro Alves
2016-05-06 12:45 ` [PATCH v3 34/34] Always switch fork child to the main UI Pedro Alves
2016-05-06 12:45 ` [PATCH v3 32/34] Send deleted watchpoint-scope output to all UIs Pedro Alves
2016-05-06 12:45 ` [PATCH v3 22/34] Fix for spurious prompts in secondary UIs Pedro Alves
2016-05-06 12:45 ` [PATCH v3 27/34] Handle UI's terminal closing Pedro Alves
2016-05-06 12:45 ` [PATCH v3 26/34] Make main_ui be heap allocated Pedro Alves
2016-05-06 12:52 ` [PATCH v3 18/34] Make raw_stdout be per MI instance Pedro Alves
2016-05-06 12:53 ` [PATCH v3 09/34] Make instream be per UI Pedro Alves
2016-05-06 12:53 ` [PATCH v3 19/34] Simplify starting the command event loop Pedro Alves
2016-05-26 18:37 ` [PATCH v3 35/34] Add "new-ui console" tests Pedro Alves
2016-06-21  0:23 ` [pushed] Re: [PATCH v3 00/34] Towards great frontend GDB consoles Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1462538104-19109-4-git-send-email-palves@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox