Multi-target support
[deliverable/binutils-gdb.git] / gdb / event-top.c
index b4a67908595128d75dae73118e08948ac6b004c9..3f10b21280d6626382932b30ffce702c9c814167 100644 (file)
@@ -1,7 +1,6 @@
 /* Top level stuff for GDB, the GNU debugger.
 
-   Copyright (C) 1999-2002, 2004-2005, 2007-2012 Free Software
-   Foundation, Inc.
+   Copyright (C) 1999-2020 Free Software Foundation, Inc.
 
    Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
 
 #include "defs.h"
 #include "top.h"
 #include "inferior.h"
+#include "infrun.h"
 #include "target.h"
-#include "terminal.h"          /* for job_control */
+#include "terminal.h"
 #include "event-loop.h"
 #include "event-top.h"
 #include "interps.h"
 #include <signal.h>
-#include "exceptions.h"
 #include "cli/cli-script.h"     /* for reset_command_nest_depth */
 #include "main.h"
 #include "gdbthread.h"
-#include "observer.h"
+#include "observable.h"
 #include "continuations.h"
 #include "gdbcmd.h"            /* for dont_repeat() */
+#include "annotate.h"
+#include "maint.h"
+#include "gdbsupport/buffer.h"
+#include "ser-event.h"
+#include "gdb_select.h"
+#include "gdbsupport/gdb-sigmask.h"
 
 /* readline include files.  */
 #include "readline/readline.h"
 /* readline defines this.  */
 #undef savestring
 
-static void rl_callback_read_char_wrapper (gdb_client_data client_data);
-static void command_line_handler (char *rl);
-static void change_line_handler (void);
-static void command_handler (char *command);
-static char *top_level_prompt (void);
+static std::string top_level_prompt ();
 
 /* Signal handlers.  */
 #ifdef SIGQUIT
@@ -68,32 +69,15 @@ static void async_do_nothing (gdb_client_data);
 static void async_disconnect (gdb_client_data);
 #endif
 static void async_float_handler (gdb_client_data);
-#ifdef STOP_SIGNAL
-static void async_stop_sig (gdb_client_data);
+#ifdef SIGTSTP
+static void async_sigtstp_handler (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.  */
 
@@ -103,19 +87,16 @@ void (*call_readline) (gdb_client_data);
    ezannoni: as of 1999-04-29 I expect that this
    variable will not be used after gdb is changed to use the event
    loop as default engine, and event-top.c is merged into top.c.  */
-int async_command_editing_p;
-
-/* This is the annotation suffix that will be used when the
-   annotation_level is 2.  */
-char *async_annotation_suffix;
+bool set_editing_cmd_var;
 
 /* This is used to display the notification of the completion of an
    asynchronous execution command.  */
-int exec_done_display_p = 0;
+bool exec_done_display_p = false;
 
-/* This is the file descriptor for the input stream that GDB uses to
-   read commands from.  */
-int input_fd;
+/* Used by the stdin event handler to compensate for missed stdin events.
+   Setting this to a non-zero value inside an stdin callback makes the callback
+   run again.  */
+int call_stdin_event_handler_again_p;
 
 /* Signal handling variables.  */
 /* Each of these is a pointer to a function that the event loop will
@@ -123,89 +104,235 @@ int input_fd;
    handlers mark these functions as ready to be executed and the event
    loop, in a later iteration, calls them.  See the function
    invoke_async_signal_handler.  */
-void *sigint_token;
+static struct async_signal_handler *sigint_token;
 #ifdef SIGHUP
-void *sighup_token;
+static struct async_signal_handler *sighup_token;
 #endif
 #ifdef SIGQUIT
-void *sigquit_token;
+static struct async_signal_handler *sigquit_token;
 #endif
-void *sigfpe_token;
-#ifdef STOP_SIGNAL
-void *sigtstp_token;
+static struct async_signal_handler *sigfpe_token;
+#ifdef SIGTSTP
+static struct async_signal_handler *sigtstp_token;
 #endif
+static struct async_signal_handler *async_sigterm_token;
 
-/* Structure to save a partially entered command.  This is used when
-   the user types '\' at the end of a command line.  This is necessary
-   because each line of input is handled by a different call to
-   command_line_handler, and normally there is no state retained
-   between different calls.  */
-static int more_to_come = 0;
-
-struct readline_input_state
-  {
-    char *linebuffer;
-    char *linebuffer_ptr;
-  }
-readline_input_state;
-
-/* This hook is called by rl_callback_read_char_wrapper after each
+/* This hook is called by gdb_rl_callback_read_char_wrapper after each
    character is processed.  */
 void (*after_char_processing_hook) (void);
 \f
 
-/* Wrapper function for calling into the readline library.  The event
-   loop expects the callback function to have a paramter, while
-   readline expects none.  */
+/* Wrapper function for calling into the readline library.  This takes
+   care of a couple things:
+
+   - The event loop expects the callback function to have a parameter,
+     while readline expects none.
+
+   - Propagation of GDB exceptions/errors thrown from INPUT_HANDLER
+     across readline requires special handling.
+
+   On the exceptions issue:
+
+   DWARF-based unwinding cannot cross code built without -fexceptions.
+   Any exception that tries to propagate through such code will fail
+   and the result is a call to std::terminate.  While some ABIs, such
+   as x86-64, require all code to be built with exception tables,
+   others don't.
+
+   This is a problem when GDB calls some non-EH-aware C library code,
+   that calls into GDB again through a callback, and that GDB callback
+   code throws a C++ exception.  Turns out this is exactly what
+   happens with GDB's readline callback.
+
+   In such cases, we must catch and save any C++ exception that might
+   be thrown from the GDB callback before returning to the
+   non-EH-aware code.  When the non-EH-aware function itself returns
+   back to GDB, we then rethrow the original C++ exception.
+
+   In the readline case however, the right thing to do is to longjmp
+   out of the callback, rather than do a normal return -- there's no
+   way for the callback to return to readline an indication that an
+   error happened, so a normal return would have rl_callback_read_char
+   potentially continue processing further input, redisplay the
+   prompt, etc.  Instead of raw setjmp/longjmp however, we use our
+   sjlj-based TRY/CATCH mechanism, which knows to handle multiple
+   levels of active setjmp/longjmp frames, needed in order to handle
+   the readline callback recursing, as happens with e.g., secondary
+   prompts / queries, through gdb_readline_wrapper.  This must be
+   noexcept in order to avoid problems with mixing sjlj and
+   (sjlj-based) C++ exceptions.  */
+
+static struct gdb_exception
+gdb_rl_callback_read_char_wrapper_noexcept () noexcept
+{
+  struct gdb_exception gdb_expt;
+
+  /* C++ exceptions can't normally be thrown across readline (unless
+     it is built with -fexceptions, but it won't by default on many
+     ABIs).  So we instead wrap the readline call with a sjlj-based
+     TRY/CATCH, and rethrow the GDB exception once back in GDB.  */
+  TRY_SJLJ
+    {
+      rl_callback_read_char ();
+      if (after_char_processing_hook)
+       (*after_char_processing_hook) ();
+    }
+  CATCH_SJLJ (ex, RETURN_MASK_ALL)
+    {
+      gdb_expt = std::move (ex);
+    }
+  END_CATCH_SJLJ
+
+  return gdb_expt;
+}
+
 static void
-rl_callback_read_char_wrapper (gdb_client_data client_data)
+gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
 {
-  rl_callback_read_char ();
-  if (after_char_processing_hook)
-    (*after_char_processing_hook) ();
+  struct gdb_exception gdb_expt
+    = gdb_rl_callback_read_char_wrapper_noexcept ();
+
+  /* Rethrow using the normal EH mechanism.  */
+  if (gdb_expt.reason < 0)
+    throw_exception (std::move (gdb_expt));
 }
 
-/* Initialize all the necessary variables, start the event loop,
-   register readline, and stdin, start the loop.  */
-void
-cli_command_loop (void)
+/* GDB's readline callback handler.  Calls the current INPUT_HANDLER,
+   and propagates GDB exceptions/errors thrown from INPUT_HANDLER back
+   across readline.  See gdb_rl_callback_read_char_wrapper.  This must
+   be noexcept in order to avoid problems with mixing sjlj and
+   (sjlj-based) C++ exceptions.  */
+
+static void
+gdb_rl_callback_handler (char *rl) noexcept
 {
-  display_gdb_prompt (0);
+  /* This is static to avoid undefined behavior when calling longjmp
+     -- gdb_exception has a destructor with side effects.  */
+  static struct gdb_exception gdb_rl_expt;
+  struct ui *ui = current_ui;
+
+  try
+    {
+      /* Ensure the exception is reset on each call.  */
+      gdb_rl_expt = {};
+      ui->input_handler (gdb::unique_xmalloc_ptr<char> (rl));
+    }
+  catch (gdb_exception &ex)
+    {
+      gdb_rl_expt = std::move (ex);
+    }
 
-  /* Now it's time to start the event loop.  */
-  start_event_loop ();
+  /* If we caught a GDB exception, longjmp out of the readline
+     callback.  There's no other way for the callback to signal to
+     readline that an error happened.  A normal return would have
+     readline potentially continue processing further input, redisplay
+     the prompt, etc.  (This is what GDB historically did when it was
+     a C program.)  Note that since we're long jumping, local variable
+     dtors are NOT run automatically.  */
+  if (gdb_rl_expt.reason < 0)
+    throw_exception_sjlj (gdb_rl_expt);
 }
 
 /* Change the function to be invoked every time there is a character
    ready on stdin.  This is used when the user sets the editing off,
    therefore bypassing readline, and letting gdb handle the input
-   itself, via gdb_readline2.  Also it is used in the opposite case in
-   which the user sets editing on again, by restoring readline
-   handling of the input.  */
-static void
-change_line_handler (void)
+   itself, via gdb_readline_no_editing_callback.  Also it is used in
+   the opposite case in which the user sets editing on again, by
+   restoring readline handling of the input.
+
+   NOTE: this operates on input_fd, not instream.  If we are reading
+   commands from a file, instream will point to the file.  However, we
+   always read commands from a file with editing off.  This means that
+   the 'set editing on/off' will have effect only on the interactive
+   session.  */
+
+void
+change_line_handler (int editing)
 {
-  /* 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
-     off.  This means that the 'set editing on/off' will have effect
-     only on the interactive session.  */
+  struct ui *ui = current_ui;
+
+  /* We can only have one instance of readline, so we only allow
+     editing on the main UI.  */
+  if (ui != main_ui)
+    return;
+
+  /* Don't try enabling editing if the interpreter doesn't support it
+     (e.g., MI).  */
+  if (!interp_supports_command_editing (top_level_interpreter ())
+      || !interp_supports_command_editing (command_interp ()))
+    return;
 
-  if (async_command_editing_p)
+  if (editing)
     {
+      gdb_assert (ui == main_ui);
+
       /* Turn on editing by using readline.  */
-      call_readline = rl_callback_read_char_wrapper;
-      input_handler = command_line_handler;
+      ui->call_readline = gdb_rl_callback_read_char_wrapper;
     }
   else
     {
-      /* Turn off editing by using gdb_readline2.  */
-      rl_callback_handler_remove ();
-      call_readline = gdb_readline2;
+      /* Turn off editing by using gdb_readline_no_editing_callback.  */
+      if (ui->command_editing)
+       gdb_rl_callback_handler_remove ();
+      ui->call_readline = gdb_readline_no_editing_callback;
+    }
+  ui->command_editing = editing;
+}
+
+/* The functions below are wrappers for rl_callback_handler_remove and
+   rl_callback_handler_install that keep track of whether the callback
+   handler is installed in readline.  This is necessary because after
+   handling a target event of a background execution command, we may
+   need to reinstall the callback handler if it was removed due to a
+   secondary prompt.  See gdb_readline_wrapper_line.  We don't
+   unconditionally install the handler for every target event because
+   that also clears the line buffer, thus installing it while the user
+   is typing would lose input.  */
+
+/* Whether we've registered a callback handler with readline.  */
+static int callback_handler_installed;
+
+/* See event-top.h, and above.  */
+
+void
+gdb_rl_callback_handler_remove (void)
+{
+  gdb_assert (current_ui == main_ui);
+
+  rl_callback_handler_remove ();
+  callback_handler_installed = 0;
+}
+
+/* See event-top.h, and above.  Note this wrapper doesn't have an
+   actual callback parameter because we always install
+   INPUT_HANDLER.  */
+
+void
+gdb_rl_callback_handler_install (const char *prompt)
+{
+  gdb_assert (current_ui == main_ui);
+
+  /* Calling rl_callback_handler_install resets readline's input
+     buffer.  Calling this when we were already processing input
+     therefore loses input.  */
+  gdb_assert (!callback_handler_installed);
 
-      /* Set up the command handler as well, in case we are called as
-         first thing from .gdbinit.  */
-      input_handler = command_line_handler;
+  rl_callback_handler_install (prompt, gdb_rl_callback_handler);
+  callback_handler_installed = 1;
+}
+
+/* See event-top.h, and above.  */
+
+void
+gdb_rl_callback_handler_reinstall (void)
+{
+  gdb_assert (current_ui == main_ui);
+
+  if (!callback_handler_installed)
+    {
+      /* Passing NULL as prompt argument tells readline to not display
+        a prompt.  */
+      gdb_rl_callback_handler_install (NULL);
     }
 }
 
@@ -227,27 +354,25 @@ change_line_handler (void)
    3. On prompting for pagination.  */
 
 void
-display_gdb_prompt (char *new_prompt)
+display_gdb_prompt (const char *new_prompt)
 {
-  char *actual_gdb_prompt = NULL;
-  struct cleanup *old_chain;
+  std::string actual_gdb_prompt;
+
+  annotate_display_prompt ();
 
   /* Reset the nesting depth used when trace-commands is set.  */
   reset_command_nest_depth ();
 
-  /* Each interpreter has its own rules on displaying the command
-     prompt.  */
-  if (!current_interp_display_prompt_p ())
-    return;
-
-  old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt);
-
   /* Do not call the python hook on an explicit prompt change as
      passed to this function, as this forms a secondary/local prompt,
      IE, displayed but not set.  */
   if (! new_prompt)
     {
-      if (sync_execution)
+      struct ui *ui = current_ui;
+
+      if (ui->prompt_state == PROMPTED)
+       internal_error (__FILE__, __LINE__, _("double prompt"));
+      else if (ui->prompt_state == PROMPT_BLOCKED)
        {
          /* This is to trick readline into not trying to display the
             prompt.  Even though we display the prompt using this
@@ -265,22 +390,24 @@ display_gdb_prompt (char *new_prompt)
             the above two functions.  Calling
             rl_callback_handler_remove(), does the job.  */
 
-         rl_callback_handler_remove ();
+         if (current_ui->command_editing)
+           gdb_rl_callback_handler_remove ();
          return;
        }
-      else
+      else if (ui->prompt_state == PROMPT_NEEDED)
        {
          /* Display the top level prompt.  */
          actual_gdb_prompt = top_level_prompt ();
+         ui->prompt_state = PROMPTED;
        }
     }
   else
-    actual_gdb_prompt = xstrdup (new_prompt);
+    actual_gdb_prompt = new_prompt;
 
-  if (async_command_editing_p)
+  if (current_ui->command_editing)
     {
-      rl_callback_handler_remove ();
-      rl_callback_handler_install (actual_gdb_prompt, input_handler);
+      gdb_rl_callback_handler_remove ();
+      gdb_rl_callback_handler_install (actual_gdb_prompt.c_str ());
     }
   /* new_prompt at this point can be the top of the stack or the one
      passed in.  It can't be NULL.  */
@@ -289,84 +416,122 @@ display_gdb_prompt (char *new_prompt)
       /* Don't use a _filtered function here.  It causes the assumed
          character position to be off, since the newline we read from
          the user is not accounted for.  */
-      fputs_unfiltered (actual_gdb_prompt, gdb_stdout);
+      fputs_unfiltered (actual_gdb_prompt.c_str (), gdb_stdout);
       gdb_flush (gdb_stdout);
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Return the top level prompt, as specified by "set prompt", possibly
-   overriden by the python gdb.prompt_hook hook, and then composed
-   with the prompt prefix and suffix (annotations).  The caller is
-   responsible for freeing the returned string.  */
+   overridden by the python gdb.prompt_hook hook, and then composed
+   with the prompt prefix and suffix (annotations).  */
 
-static char *
+static std::string
 top_level_prompt (void)
 {
-  char *prefix;
-  char *prompt = NULL;
-  char *suffix;
-  char *composed_prompt;
-  size_t prompt_length;
+  char *prompt;
 
   /* Give observers a chance of changing the prompt.  E.g., the python
      `gdb.prompt_hook' is installed as an observer.  */
-  observer_notify_before_prompt (get_prompt ());
+  gdb::observers::before_prompt.notify (get_prompt ());
 
-  prompt = xstrdup (get_prompt ());
+  prompt = get_prompt ();
 
   if (annotation_level >= 2)
     {
       /* Prefix needs to have new line at end.  */
-      prefix = (char *) alloca (strlen (async_annotation_suffix) + 10);
-      strcpy (prefix, "\n\032\032pre-");
-      strcat (prefix, async_annotation_suffix);
-      strcat (prefix, "\n");
+      const char prefix[] = "\n\032\032pre-prompt\n";
 
       /* Suffix needs to have a new line at end and \032 \032 at
         beginning.  */
-      suffix = (char *) alloca (strlen (async_annotation_suffix) + 6);
-      strcpy (suffix, "\n\032\032");
-      strcat (suffix, async_annotation_suffix);
-      strcat (suffix, "\n");
-    }
-  else
-    {
-      prefix = "";
-      suffix = "";
+      const char suffix[] = "\n\032\032prompt\n";
+
+      return std::string (prefix) + prompt + suffix;
     }
 
-  prompt_length = strlen (prefix) + strlen (prompt) + strlen (suffix);
-  composed_prompt = xmalloc (prompt_length + 1);
+  return prompt;
+}
+
+/* See top.h.  */
 
-  strcpy (composed_prompt, prefix);
-  strcat (composed_prompt, prompt);
-  strcat (composed_prompt, suffix);
+struct ui *main_ui;
+struct ui *current_ui;
+struct ui *ui_list;
 
-  xfree (prompt);
+/* Get a pointer to the current UI's line buffer.  This is used to
+   construct a whole line of input from partial input.  */
 
-  return composed_prompt;
+static struct buffer *
+get_command_line_buffer (void)
+{
+  return &current_ui->line_buffer;
 }
 
-/* When there is an event ready on the stdin file desriptor, instead
+/* When there is an event ready on the stdin file descriptor, instead
    of calling readline directly throught the callback function, or
-   instead of calling gdb_readline2, give gdb a chance to detect
-   errors and do something.  */
+   instead of calling gdb_readline_no_editing_callback, give gdb a
+   chance to detect errors and do something.  */
+
 void
 stdin_event_handler (int error, gdb_client_data client_data)
 {
+  struct ui *ui = (struct ui *) client_data;
+
   if (error)
     {
-      printf_unfiltered (_("error detected on stdin\n"));
-      delete_file_handler (input_fd);
-      discard_all_continuations ();
-      discard_all_intermediate_continuations ();
-      /* If stdin died, we may as well kill gdb.  */
-      quit_command ((char *) 0, stdin == instream);
+      /* Switch to the main UI, so diagnostics always go there.  */
+      current_ui = main_ui;
+
+      delete_file_handler (ui->input_fd);
+      if (main_ui == ui)
+       {
+         /* If stdin died, we may as well kill gdb.  */
+         printf_unfiltered (_("error detected on stdin\n"));
+         quit_command ((char *) 0, 0);
+       }
+      else
+       {
+         /* Simply delete the UI.  */
+         delete ui;
+       }
     }
   else
-    (*call_readline) (client_data);
+    {
+      /* Switch to the UI whose input descriptor woke up the event
+        loop.  */
+      current_ui = ui;
+
+      /* This makes sure a ^C immediately followed by further input is
+        always processed in that order.  E.g,. with input like
+        "^Cprint 1\n", the SIGINT handler runs, marks the async
+        signal handler, and then select/poll may return with stdin
+        ready, instead of -1/EINTR.  The
+        gdb.base/double-prompt-target-event-error.exp test exercises
+        this.  */
+      QUIT;
+
+      do
+       {
+         call_stdin_event_handler_again_p = 0;
+         ui->call_readline (client_data);
+       }
+      while (call_stdin_event_handler_again_p != 0);
+    }
+}
+
+/* See top.h.  */
+
+void
+ui_register_input_event_handler (struct ui *ui)
+{
+  add_file_handler (ui->input_fd, stdin_event_handler, ui);
+}
+
+/* See top.h.  */
+
+void
+ui_unregister_input_event_handler (struct ui *ui)
+{
+  delete_file_handler (ui->input_fd);
 }
 
 /* Re-enable stdin after the end of an execution command in
@@ -376,14 +541,13 @@ stdin_event_handler (int error, gdb_client_data client_data)
 void
 async_enable_stdin (void)
 {
-  if (sync_execution)
+  struct ui *ui = current_ui;
+
+  if (ui->prompt_state == PROMPT_BLOCKED)
     {
-      /* See NOTE in async_disable_stdin().  */
-      /* FIXME: cagney/1999-09-27: Call this before clearing
-        sync_execution.  Current target_terminal_ours() implementations
-        check for sync_execution before switching the terminal.  */
-      target_terminal_ours ();
-      sync_execution = 0;
+      target_terminal::ours ();
+      ui_register_input_event_handler (ui);
+      ui->prompt_state = PROMPT_NEEDED;
     }
 }
 
@@ -393,265 +557,239 @@ async_enable_stdin (void)
 void
 async_disable_stdin (void)
 {
-  sync_execution = 1;
+  struct ui *ui = current_ui;
+
+  ui->prompt_state = PROMPT_BLOCKED;
+  delete_file_handler (ui->input_fd);
 }
 \f
 
-/* Handles a gdb command.  This function is called by
-   command_line_handler, which has processed one or more input lines
-   into COMMAND.  */
-/* NOTE: 1999-04-30 This is the asynchronous version of the command_loop
-   function.  The command_loop function will be obsolete when we
-   switch to use the event loop at every execution of gdb.  */
-static void
-command_handler (char *command)
+/* Handle a gdb command line.  This function is called when
+   handle_line_of_input has concatenated one or more input lines into
+   a whole command.  */
+
+void
+command_handler (const char *command)
 {
-  int stdin_is_tty = ISATTY (stdin);
-  struct cleanup *stat_chain;
+  struct ui *ui = current_ui;
+  const char *c;
 
-  quit_flag = 0;
-  if (instream == stdin && stdin_is_tty)
+  if (ui->instream == ui->stdin_stream)
     reinitialize_more_filter ();
 
-  /* If readline returned a NULL command, it means that the connection
-     with the terminal is gone.  This happens at the end of a
-     testsuite run, after Expect has hung up but GDB is still alive.
-     In such a case, we just quit gdb killing the inferior program
-     too.  */
-  if (command == 0)
-    {
-      printf_unfiltered ("quit\n");
-      execute_command ("quit", stdin == instream);
-    }
-
-  stat_chain = make_command_stats_cleanup (1);
-
-  execute_command (command, instream == stdin);
+  scoped_command_stats stat_reporter (true);
 
-  /* Do any commands attached to breakpoint we stopped at.  */
-  bpstat_do_actions ();
+  /* Do not execute commented lines.  */
+  for (c = command; *c == ' ' || *c == '\t'; c++)
+    ;
+  if (c[0] != '#')
+    {
+      execute_command (command, ui->instream == ui->stdin_stream);
 
-  do_cleanups (stat_chain);
+      /* Do any commands attached to breakpoint we stopped at.  */
+      bpstat_do_actions ();
+    }
 }
 
-/* Handle a complete line of input.  This is called by the callback
-   mechanism within the readline library.  Deal with incomplete
-   commands as well, by saving the partial input in a global
-   buffer.  */
+/* Append RL, an input line returned by readline or one of its
+   emulations, to CMD_LINE_BUFFER.  Returns the command line if we
+   have a whole command line ready to be processed by the command
+   interpreter or NULL if the command line isn't complete yet (input
+   line ends in a backslash).  */
 
-/* NOTE: 1999-04-30 This is the asynchronous version of the
-   command_line_input function; command_line_input will become
-   obsolete once we use the event loop as the default mechanism in
-   GDB.  */
-static void
-command_line_handler (char *rl)
+static char *
+command_line_append_input_line (struct buffer *cmd_line_buffer, const char *rl)
 {
-  static char *linebuffer = 0;
-  static unsigned linelength = 0;
-  char *p;
-  char *p1;
-  char *nline;
-  char got_eof = 0;
+  char *cmd;
+  size_t len;
 
-  int repeat = (instream == stdin);
+  len = strlen (rl);
 
-  if (annotation_level > 1 && instream == stdin)
+  if (len > 0 && rl[len - 1] == '\\')
     {
-      printf_unfiltered (("\n\032\032post-"));
-      puts_unfiltered (async_annotation_suffix);
-      printf_unfiltered (("\n"));
+      /* Don't copy the backslash and wait for more.  */
+      buffer_grow (cmd_line_buffer, rl, len - 1);
+      cmd = NULL;
     }
-
-  if (linebuffer == 0)
+  else
     {
-      linelength = 80;
-      linebuffer = (char *) xmalloc (linelength);
+      /* Copy whole line including terminating null, and we're
+        done.  */
+      buffer_grow (cmd_line_buffer, rl, len + 1);
+      cmd = cmd_line_buffer->buffer;
     }
 
-  p = linebuffer;
+  return cmd;
+}
 
-  if (more_to_come)
-    {
-      strcpy (linebuffer, readline_input_state.linebuffer);
-      p = readline_input_state.linebuffer_ptr;
-      xfree (readline_input_state.linebuffer);
-      more_to_come = 0;
-    }
+/* Handle a line of input coming from readline.
 
-#ifdef STOP_SIGNAL
-  if (job_control)
-    signal (STOP_SIGNAL, handle_stop_sig);
-#endif
+   If the read line ends with a continuation character (backslash),
+   save the partial input in CMD_LINE_BUFFER (except the backslash),
+   and return NULL.  Otherwise, save the partial input and return a
+   pointer to CMD_LINE_BUFFER's buffer (null terminated), indicating a
+   whole command line is ready to be executed.
 
-  /* Make sure that all output has been output.  Some machines may let
-     you get away with leaving out some of the gdb_flush, but not
-     all.  */
-  wrap_here ("");
-  gdb_flush (gdb_stdout);
-  gdb_flush (gdb_stderr);
+   Returns EOF on end of file.
 
-  if (source_file_name != NULL)
-    ++source_line_number;
+   If REPEAT, handle command repetitions:
 
-  /* If we are in this case, then command_handler will call quit 
-     and exit from gdb.  */
-  if (!rl || rl == (char *) EOF)
-    {
-      got_eof = 1;
-      command_handler (0);
-      return;                  /* Lint.  */
-    }
-  if (strlen (rl) + 1 + (p - linebuffer) > linelength)
-    {
-      linelength = strlen (rl) + 1 + (p - linebuffer);
-      nline = (char *) xrealloc (linebuffer, linelength);
-      p += nline - linebuffer;
-      linebuffer = nline;
-    }
-  p1 = rl;
-  /* Copy line.  Don't copy null at end.  (Leaves line alone
-     if this was just a newline).  */
-  while (*p1)
-    *p++ = *p1++;
+     - If the input command line is NOT empty, the command returned is
+       saved using save_command_line () so that it can be repeated later.
 
-  xfree (rl);                  /* Allocated in readline.  */
+     - OTOH, if the input command line IS empty, return the saved
+       command instead of the empty input line.
+*/
 
-  if (p > linebuffer && *(p - 1) == '\\')
-    {
-      *p = '\0';
-      p--;                     /* Put on top of '\'.  */
+char *
+handle_line_of_input (struct buffer *cmd_line_buffer,
+                     const char *rl, int repeat,
+                     const char *annotation_suffix)
+{
+  struct ui *ui = current_ui;
+  int from_tty = ui->instream == ui->stdin_stream;
+  char *p1;
+  char *cmd;
 
-      readline_input_state.linebuffer = xstrdup (linebuffer);
-      readline_input_state.linebuffer_ptr = p;
+  if (rl == NULL)
+    return (char *) EOF;
 
-      /* We will not invoke a execute_command if there is more
-        input expected to complete the command.  So, we need to
-        print an empty prompt here.  */
-      more_to_come = 1;
-      display_gdb_prompt ("");
-      return;
-    }
+  cmd = command_line_append_input_line (cmd_line_buffer, rl);
+  if (cmd == NULL)
+    return NULL;
 
-#ifdef STOP_SIGNAL
-  if (job_control)
-    signal (STOP_SIGNAL, SIG_DFL);
-#endif
+  /* We have a complete command line now.  Prepare for the next
+     command, but leave ownership of memory to the buffer .  */
+  cmd_line_buffer->used_size = 0;
+
+  if (from_tty && annotation_level > 1)
+    {
+      printf_unfiltered (("\n\032\032post-"));
+      puts_unfiltered (annotation_suffix);
+      printf_unfiltered (("\n"));
+    }
 
-#define SERVER_COMMAND_LENGTH 7
-  server_command =
-    (p - linebuffer > SERVER_COMMAND_LENGTH)
-    && strncmp (linebuffer, "server ", SERVER_COMMAND_LENGTH) == 0;
+#define SERVER_COMMAND_PREFIX "server "
+  server_command = startswith (cmd, SERVER_COMMAND_PREFIX);
   if (server_command)
     {
-      /* Note that we don't set `line'.  Between this and the check in
-         dont_repeat, this insures that repeating will still do the
-         right thing.  */
-      *p = '\0';
-      command_handler (linebuffer + SERVER_COMMAND_LENGTH);
-      display_gdb_prompt (0);
-      return;
+      /* Note that we don't call `save_command_line'.  Between this
+         and the check in dont_repeat, this insures that repeating
+         will still do the right thing.  */
+      return cmd + strlen (SERVER_COMMAND_PREFIX);
     }
 
   /* Do history expansion if that is wished.  */
-  if (history_expansion_p && instream == stdin
-      && ISATTY (instream))
+  if (history_expansion_p && from_tty && input_interactive_p (current_ui))
     {
-      char *history_value;
+      char *cmd_expansion;
       int expanded;
 
-      *p = '\0';               /* Insert null now.  */
-      expanded = history_expand (linebuffer, &history_value);
+      expanded = history_expand (cmd, &cmd_expansion);
+      gdb::unique_xmalloc_ptr<char> history_value (cmd_expansion);
       if (expanded)
        {
+         size_t len;
+
          /* Print the changes.  */
-         printf_unfiltered ("%s\n", history_value);
+         printf_unfiltered ("%s\n", history_value.get ());
 
          /* If there was an error, call this function again.  */
          if (expanded < 0)
-           {
-             xfree (history_value);
-             return;
-           }
-         if (strlen (history_value) > linelength)
-           {
-             linelength = strlen (history_value) + 1;
-             linebuffer = (char *) xrealloc (linebuffer, linelength);
-           }
-         strcpy (linebuffer, history_value);
-         p = linebuffer + strlen (linebuffer);
+           return cmd;
+
+         /* history_expand returns an allocated string.  Just replace
+            our buffer with it.  */
+         len = strlen (history_value.get ());
+         xfree (buffer_finish (cmd_line_buffer));
+         cmd_line_buffer->buffer = history_value.get ();
+         cmd_line_buffer->buffer_size = len + 1;
+         cmd = history_value.release ();
        }
-      xfree (history_value);
     }
 
   /* If we just got an empty line, and that is supposed to repeat the
-     previous command, return the value in the global buffer.  */
-  if (repeat && p == linebuffer && *p != '\\')
-    {
-      command_handler (saved_command_line);
-      display_gdb_prompt (0);
-      return;
-    }
+     previous command, return the previously saved command.  */
+  for (p1 = cmd; *p1 == ' ' || *p1 == '\t'; p1++)
+    ;
+  if (repeat && *p1 == '\0')
+    return get_saved_command_line ();
+
+  /* Add command to history if appropriate.  Note: lines consisting
+     solely of comments are also added to the command history.  This
+     is useful when you type a command, and then realize you don't
+     want to execute it quite yet.  You can comment out the command
+     and then later fetch it from the value history and remove the
+     '#'.  The kill ring is probably better, but some people are in
+     the habit of commenting things out.  */
+  if (*cmd != '\0' && from_tty && input_interactive_p (current_ui))
+    gdb_add_history (cmd);
 
-  for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
-  if (repeat && !*p1)
+  /* Save into global buffer if appropriate.  */
+  if (repeat)
     {
-      command_handler (saved_command_line);
-      display_gdb_prompt (0);
-      return;
+      save_command_line (cmd);
+      return get_saved_command_line ();
     }
+  else
+    return cmd;
+}
 
-  *p = 0;
+/* Handle a complete line of input.  This is called by the callback
+   mechanism within the readline library.  Deal with incomplete
+   commands as well, by saving the partial input in a global
+   buffer.
 
-  /* Add line to history if appropriate.  */
-  if (instream == stdin
-      && ISATTY (stdin) && *linebuffer)
-    add_history (linebuffer);
+   NOTE: This is the asynchronous version of the command_line_input
+   function.  */
 
-  /* Note: lines consisting solely of comments are added to the command
-     history.  This is useful when you type a command, and then
-     realize you don't want to execute it quite yet.  You can comment
-     out the command and then later fetch it from the value history
-     and remove the '#'.  The kill ring is probably better, but some
-     people are in the habit of commenting things out.  */
-  if (*p1 == '#')
-    *p1 = '\0';                        /* Found a comment.  */
+void
+command_line_handler (gdb::unique_xmalloc_ptr<char> &&rl)
+{
+  struct buffer *line_buffer = get_command_line_buffer ();
+  struct ui *ui = current_ui;
+  char *cmd;
 
-  /* Save into global buffer if appropriate.  */
-  if (repeat)
+  cmd = handle_line_of_input (line_buffer, rl.get (), 1, "prompt");
+  if (cmd == (char *) EOF)
     {
-      if (linelength > saved_command_line_size)
-       {
-         saved_command_line = xrealloc (saved_command_line, linelength);
-         saved_command_line_size = linelength;
-       }
-      strcpy (saved_command_line, linebuffer);
-      if (!more_to_come)
-       {
-         command_handler (saved_command_line);
-         display_gdb_prompt (0);
-       }
-      return;
+      /* stdin closed.  The connection with the terminal is gone.
+        This happens at the end of a testsuite run, after Expect has
+        hung up but GDB is still alive.  In such a case, we just quit
+        gdb killing the inferior program too.  */
+      printf_unfiltered ("quit\n");
+      execute_command ("quit", 1);
+    }
+  else if (cmd == NULL)
+    {
+      /* We don't have a full line yet.  Print an empty prompt.  */
+      display_gdb_prompt ("");
     }
+  else
+    {
+      ui->prompt_state = PROMPT_NEEDED;
+
+      command_handler (cmd);
 
-  command_handler (linebuffer);
-  display_gdb_prompt (0);
-  return;
+      if (ui->prompt_state != PROMPTED)
+       display_gdb_prompt (0);
+    }
 }
 
 /* Does reading of input from terminal w/o the editing features
-   provided by the readline library.  */
+   provided by the readline library.  Calls the line input handler
+   once we have a whole input line.  */
 
-/* NOTE: 1999-04-30 Asynchronous version of gdb_readline; gdb_readline
-   will become obsolete when the event loop is made the default
-   execution for gdb.  */
 void
-gdb_readline2 (gdb_client_data client_data)
+gdb_readline_no_editing_callback (gdb_client_data client_data)
 {
   int c;
   char *result;
-  int input_index = 0;
-  int result_size = 80;
+  struct buffer line_buffer;
   static int done_once = 0;
+  struct ui *ui = current_ui;
+
+  buffer_init (&line_buffer);
 
   /* Unbuffer the input stream, so that, later on, the calls to fgetc
      fetch only one char at the time from the stream.  The fgetc's will
@@ -659,59 +797,102 @@ gdb_readline2 (gdb_client_data client_data)
      stream after '\n'.  If we buffer the input and fgetc drains the
      stream, getting stuff beyond the newline as well, a select, done
      afterwards will not trigger.  */
-  if (!done_once && !ISATTY (instream))
+  if (!done_once && !ISATTY (ui->instream))
     {
-      setbuf (instream, NULL);
+      setbuf (ui->instream, NULL);
       done_once = 1;
     }
 
-  result = (char *) xmalloc (result_size);
-
   /* We still need the while loop here, even though it would seem
-     obvious to invoke gdb_readline2 at every character entered.  If
-     not using the readline library, the terminal is in cooked mode,
-     which sends the characters all at once.  Poll will notice that the
-     input fd has changed state only after enter is pressed.  At this
-     point we still need to fetch all the chars entered.  */
+     obvious to invoke gdb_readline_no_editing_callback at every
+     character entered.  If not using the readline library, the
+     terminal is in cooked mode, which sends the characters all at
+     once.  Poll will notice that the input fd has changed state only
+     after enter is pressed.  At this point we still need to fetch all
+     the chars entered.  */
 
   while (1)
     {
       /* Read from stdin if we are executing a user defined command.
          This is the right thing for prompt_for_continue, at least.  */
-      c = fgetc (instream ? instream : stdin);
+      c = fgetc (ui->instream != NULL ? ui->instream : ui->stdin_stream);
 
       if (c == EOF)
        {
-         if (input_index > 0)
-           /* The last line does not end with a newline.  Return it,
-              and if we are called again fgetc will still return EOF
-              and we'll return NULL then.  */
-           break;
-         xfree (result);
-         (*input_handler) (0);
+         if (line_buffer.used_size > 0)
+           {
+             /* The last line does not end with a newline.  Return it, and
+                if we are called again fgetc will still return EOF and
+                we'll return NULL then.  */
+             break;
+           }
+         xfree (buffer_finish (&line_buffer));
+         ui->input_handler (NULL);
          return;
        }
 
       if (c == '\n')
        {
-         if (input_index > 0 && result[input_index - 1] == '\r')
-           input_index--;
+         if (line_buffer.used_size > 0
+             && line_buffer.buffer[line_buffer.used_size - 1] == '\r')
+           line_buffer.used_size--;
          break;
        }
 
-      result[input_index++] = c;
-      while (input_index >= result_size)
-       {
-         result_size *= 2;
-         result = (char *) xrealloc (result, result_size);
-       }
+      buffer_grow_char (&line_buffer, c);
     }
 
-  result[input_index++] = '\0';
-  (*input_handler) (result);
+  buffer_grow_char (&line_buffer, '\0');
+  result = buffer_finish (&line_buffer);
+  ui->input_handler (gdb::unique_xmalloc_ptr<char> (result));
+}
+\f
+
+/* See event-top.h.  */
+
+thread_local void (*thread_local_segv_handler) (int);
+
+static void handle_sigsegv (int sig);
+
+/* Install the SIGSEGV handler.  */
+static void
+install_handle_sigsegv ()
+{
+#if defined (HAVE_SIGACTION)
+  struct sigaction sa;
+  sa.sa_handler = handle_sigsegv;
+  sigemptyset (&sa.sa_mask);
+#ifdef HAVE_SIGALTSTACK
+  sa.sa_flags = SA_ONSTACK;
+#else
+  sa.sa_flags = 0;
+#endif
+  sigaction (SIGSEGV, &sa, nullptr);
+#else
+  signal (SIGSEGV, handle_sigsegv);
+#endif
+}
+
+/* Handler for SIGSEGV.  */
+
+static void
+handle_sigsegv (int sig)
+{
+  install_handle_sigsegv ();
+
+  if (thread_local_segv_handler == nullptr)
+    abort ();                  /* ARI: abort */
+  thread_local_segv_handler (sig);
 }
+
 \f
 
+/* The serial event associated with the QUIT flag.  set_quit_flag sets
+   this, and check_quit_flag clears it.  Used by interruptible_select
+   to be able to do interruptible I/O with no race with the SIGINT
+   handler.  */
+static struct serial_event *quit_serial_event;
+
 /* Initialization of signal handlers and tokens.  There is a function
    handle_sig* for each of the signals GDB cares about.  Specifically:
    SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH.  These
@@ -727,10 +908,16 @@ gdb_readline2 (gdb_client_data client_data)
 void
 async_init_signals (void)
 {
+  initialize_async_signal_handlers ();
+
+  quit_serial_event = make_serial_event ();
+
   signal (SIGINT, handle_sigint);
   sigint_token =
     create_async_signal_handler (async_request_quit, NULL);
   signal (SIGTERM, handle_sigterm);
+  async_sigterm_token
+    = create_async_signal_handler (async_sigterm_handler, NULL);
 
   /* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
      to the inferior and breakpoints will be ignored.  */
@@ -763,21 +950,58 @@ async_init_signals (void)
   sigfpe_token =
     create_async_signal_handler (async_float_handler, NULL);
 
-#ifdef STOP_SIGNAL
+#ifdef SIGTSTP
   sigtstp_token =
-    create_async_signal_handler (async_stop_sig, NULL);
+    create_async_signal_handler (async_sigtstp_handler, NULL);
 #endif
 
+  install_handle_sigsegv ();
 }
 
+/* See defs.h.  */
+
 void
-mark_async_signal_handler_wrapper (void *token)
+quit_serial_event_set (void)
 {
-  mark_async_signal_handler ((struct async_signal_handler *) token);
+  serial_event_set (quit_serial_event);
 }
 
-/* Tell the event loop what to do if SIGINT is received.
-   See event-signal.c.  */
+/* See defs.h.  */
+
+void
+quit_serial_event_clear (void)
+{
+  serial_event_clear (quit_serial_event);
+}
+
+/* Return the selectable file descriptor of the serial event
+   associated with the quit flag.  */
+
+static int
+quit_serial_event_fd (void)
+{
+  return serial_event_fd (quit_serial_event);
+}
+
+/* See defs.h.  */
+
+void
+default_quit_handler (void)
+{
+  if (check_quit_flag ())
+    {
+      if (target_terminal::is_ours ())
+       quit ();
+      else
+       target_pass_ctrlc ();
+    }
+}
+
+/* See defs.h.  */
+quit_handler_ftype *quit_handler = default_quit_handler;
+
+/* Handle a SIGINT.  */
+
 void
 handle_sigint (int sig)
 {
@@ -787,27 +1011,71 @@ handle_sigint (int sig)
      it may be quite a while before we get back to the event loop.  So
      set quit_flag to 1 here.  Then if QUIT is called before we get to
      the event loop, we will unwind as expected.  */
+  set_quit_flag ();
 
-  quit_flag = 1;
-
-  /* If immediate_quit is set, we go ahead and process the SIGINT right
-     away, even if we usually would defer this to the event loop.  The
-     assumption here is that it is safe to process ^C immediately if
-     immediate_quit is set.  If we didn't, SIGINT would be really
-     processed only the next time through the event loop.  To get to
-     that point, though, the command that we want to interrupt needs to
-     finish first, which is unacceptable.  If immediate quit is not set,
-     we process SIGINT the next time through the loop, which is fine.  */
-  gdb_call_async_signal_handler (sigint_token, immediate_quit);
+  /* In case nothing calls QUIT before the event loop is reached, the
+     event loop handles it.  */
+  mark_async_signal_handler (sigint_token);
 }
 
+/* See gdb_select.h.  */
+
+int
+interruptible_select (int n,
+                     fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+                     struct timeval *timeout)
+{
+  fd_set my_readfds;
+  int fd;
+  int res;
+
+  if (readfds == NULL)
+    {
+      readfds = &my_readfds;
+      FD_ZERO (&my_readfds);
+    }
+
+  fd = quit_serial_event_fd ();
+  FD_SET (fd, readfds);
+  if (n <= fd)
+    n = fd + 1;
+
+  do
+    {
+      res = gdb_select (n, readfds, writefds, exceptfds, timeout);
+    }
+  while (res == -1 && errno == EINTR);
+
+  if (res == 1 && FD_ISSET (fd, readfds))
+    {
+      errno = EINTR;
+      return -1;
+    }
+  return res;
+}
+
+/* Handle GDB exit upon receiving SIGTERM if target_can_async_p ().  */
+
+static void
+async_sigterm_handler (gdb_client_data arg)
+{
+  quit_force (NULL, 0);
+}
+
+/* See defs.h.  */
+volatile int sync_quit_force_run;
+
 /* Quit GDB if SIGTERM is received.
    GDB would quit anyway, but this way it will clean up properly.  */
 void
 handle_sigterm (int sig)
 {
   signal (sig, handle_sigterm);
-  quit_force ((char *) 0, stdin == instream);
+
+  sync_quit_force_run = 1;
+  set_quit_flag ();
+
+  mark_async_signal_handler (async_sigterm_token);
 }
 
 /* Do the quit.  All the checks have been done by the caller.  */
@@ -817,11 +1085,8 @@ async_request_quit (gdb_client_data arg)
   /* If the quit_flag has gotten reset back to 0 by the time we get
      back here, that means that an exception was thrown to unwind the
      current command before we got back to the event loop.  So there
-     is no reason to call quit again here, unless immediate_quit is
-     set.  */
-
-  if (quit_flag || immediate_quit)
-    quit ();
+     is no reason to call quit again here.  */
+  QUIT;
 }
 
 #ifdef SIGQUIT
@@ -830,7 +1095,7 @@ async_request_quit (gdb_client_data arg)
 static void
 handle_sigquit (int sig)
 {
-  mark_async_signal_handler_wrapper (sigquit_token);
+  mark_async_signal_handler (sigquit_token);
   signal (sig, handle_sigquit);
 }
 #endif
@@ -851,7 +1116,7 @@ async_do_nothing (gdb_client_data arg)
 static void
 handle_sighup (int sig)
 {
-  mark_async_signal_handler_wrapper (sighup_token);
+  mark_async_signal_handler (sighup_token);
   signal (sig, handle_sighup);
 }
 
@@ -859,23 +1124,29 @@ handle_sighup (int sig)
 static void
 async_disconnect (gdb_client_data arg)
 {
-  volatile struct gdb_exception exception;
 
-  TRY_CATCH (exception, RETURN_MASK_ALL)
+  try
     {
       quit_cover ();
     }
 
-  if (exception.reason < 0)
+  catch (const gdb_exception &exception)
     {
       fputs_filtered ("Could not kill the program being debugged",
                      gdb_stderr);
       exception_print (gdb_stderr, exception);
     }
 
-  TRY_CATCH (exception, RETURN_MASK_ALL)
+  for (inferior *inf : all_inferiors ())
     {
-      pop_all_targets (1);
+      switch_to_inferior_no_thread (inf);
+      try
+       {
+         pop_all_targets ();
+       }
+      catch (const gdb_exception &exception)
+       {
+       }
     }
 
   signal (SIGHUP, SIG_DFL);    /*FIXME: ???????????  */
@@ -883,36 +1154,32 @@ async_disconnect (gdb_client_data arg)
 }
 #endif
 
-#ifdef STOP_SIGNAL
+#ifdef SIGTSTP
 void
-handle_stop_sig (int sig)
+handle_sigtstp (int sig)
 {
-  mark_async_signal_handler_wrapper (sigtstp_token);
-  signal (sig, handle_stop_sig);
+  mark_async_signal_handler (sigtstp_token);
+  signal (sig, handle_sigtstp);
 }
 
 static void
-async_stop_sig (gdb_client_data arg)
+async_sigtstp_handler (gdb_client_data arg)
 {
   char *prompt = get_prompt ();
 
-#if STOP_SIGNAL == SIGTSTP
   signal (SIGTSTP, SIG_DFL);
 #if HAVE_SIGPROCMASK
   {
     sigset_t zero;
 
     sigemptyset (&zero);
-    sigprocmask (SIG_SETMASK, &zero, 0);
+    gdb_sigmask (SIG_SETMASK, &zero, 0);
   }
 #elif HAVE_SIGSETMASK
   sigsetmask (0);
 #endif
   raise (SIGTSTP);
-  signal (SIGTSTP, handle_stop_sig);
-#else
-  signal (STOP_SIGNAL, handle_stop_sig);
-#endif
+  signal (SIGTSTP, handle_sigtstp);
   printf_unfiltered ("%s", prompt);
   gdb_flush (gdb_stdout);
 
@@ -920,18 +1187,18 @@ async_stop_sig (gdb_client_data arg)
      nothing.  */
   dont_repeat ();
 }
-#endif /* STOP_SIGNAL */
+#endif /* SIGTSTP */
 
 /* Tell the event loop what to do if SIGFPE is received.
    See event-signal.c.  */
 static void
 handle_sigfpe (int sig)
 {
-  mark_async_signal_handler_wrapper (sigfpe_token);
+  mark_async_signal_handler (sigfpe_token);
   signal (sig, handle_sigfpe);
 }
 
-/* Event loop will call this functin to process a SIGFPE.  */
+/* Event loop will call this function to process a SIGFPE.  */
 static void
 async_float_handler (gdb_client_data arg)
 {
@@ -941,78 +1208,66 @@ async_float_handler (gdb_client_data arg)
 }
 \f
 
-/* Called by do_setshow_command.  */
-void
-set_async_editing_command (char *args, int from_tty,
-                          struct cmd_list_element *c)
-{
-  change_line_handler ();
-}
-
 /* Set things up for readline to be invoked via the alternate
-   interface, i.e. via a callback function (rl_callback_read_char),
-   and hook up instream to the event loop.  */
+   interface, i.e. via a callback function
+   (gdb_rl_callback_read_char), and hook up instream to the event
+   loop.  */
+
 void
-gdb_setup_readline (void)
+gdb_setup_readline (int editing)
 {
+  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
      time.  */
   if (!batch_silent)
-    gdb_stdout = stdio_fileopen (stdout);
-  gdb_stderr = stdio_fileopen (stderr);
+    gdb_stdout = new stdio_file (ui->outstream);
+  gdb_stderr = new stderr_file (ui->errstream);
   gdb_stdlog = gdb_stderr;  /* for moment */
   gdb_stdtarg = gdb_stderr; /* for moment */
   gdb_stdtargerr = gdb_stderr; /* for moment */
 
-  /* If the input stream is connected to a terminal, turn on
-     editing.  */
-  if (ISATTY (instream))
+  /* If the input stream is connected to a terminal, turn on editing.
+     However, that is only allowed on the main UI, as we can only have
+     one instance of readline.  */
+  if (ISATTY (ui->instream) && editing && ui == main_ui)
     {
       /* Tell gdb that we will be using the readline library.  This
         could be overwritten by a command in .gdbinit like 'set
         editing on' or 'off'.  */
-      async_command_editing_p = 1;
-         
+      ui->command_editing = 1;
+
       /* When a character is detected on instream by select or poll,
         readline will be invoked via this callback function.  */
-      call_readline = rl_callback_read_char_wrapper;
+      ui->call_readline = gdb_rl_callback_read_char_wrapper;
+
+      /* Tell readline to use the same input stream that gdb uses.  */
+      rl_instream = ui->instream;
     }
   else
     {
-      async_command_editing_p = 0;
-      call_readline = gdb_readline2;
+      ui->command_editing = 0;
+      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;
-      
-  /* Tell readline to use the same input stream that gdb uses.  */
-  rl_instream = instream;
-
-  /* Get a file descriptor for the input stream, so that we can
-     register it with the event loop.  */
-  input_fd = fileno (instream);
-
-  /* Now we need to create the event sources for the input file
-     descriptor.  */
-  /* At this point in time, this is the only event source that we
-     register with the even loop.  Another source is going to be the
-     target program (inferior), but that must be registered only when
-     it actually exists (I.e. after we say 'run' or after we connect
-     to a remote target.  */
-  add_file_handler (input_fd, stdin_event_handler, 0);
+
+  /* Now create the event source for this UI's input file descriptor.
+     Another source is going to be the target program (inferior), but
+     that must be registered only when it actually exists (I.e. after
+     we say 'run' or after we connect to a remote target.  */
+  ui_register_input_event_handler (ui);
 }
 
 /* Disable command input through the standard CLI channels.  Used in
    the suspend proc for interpreters that use the standard gdb readline
    interface, like the cli & the mi.  */
+
 void
 gdb_disable_readline (void)
 {
+  struct ui *ui = current_ui;
+
   /* FIXME - It is too heavyweight to delete and remake these every
      time you run an interpreter that needs readline.  It is probably
      better to have the interpreters cache these, which in turn means
@@ -1026,6 +1281,7 @@ gdb_disable_readline (void)
   gdb_stdtargerr = NULL;
 #endif
 
-  rl_callback_handler_remove ();
-  delete_file_handler (input_fd);
+  if (ui->command_editing)
+    gdb_rl_callback_handler_remove ();
+  delete_file_handler (ui->input_fd);
 }
This page took 0.068209 seconds and 4 git commands to generate.