Make stdin be per UI
authorPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:54 +0000 (01:11 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:54 +0000 (01:11 +0100)
This commit makes each UI have its own "stdin" stream pointer.  This
is used to determine whether the "from_tty" argument to
execute_command, etc. should be true.

Related, this commit makes input_from_terminal_p take an UI parameter,
and then avoids the gdb_has_a_terminal in it.  gdb_has_a_terminal only
returns info on gdb's own main/primary terminal (the real stdin).
However, the places that call input_from_terminal_p really want to
know is whether the command came from an interactive tty.  This patch
thus renames input_from_terminal_p to input_interactive_p for clarity,
and then makes input_interactive_p check for "set interactive" itself,
along with ISATTY, instead of calling gdb_has_a_terminal.  Actually,
quit_force wants to call input_interactive_p _after_ stdin is closed,
we can't call ISATTY that late.  So instead we save the result of
ISATTY in a field of the UI.

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

* cli/cli-script.c (read_next_line): Adjust to per-UI stdin.
(read_command_lines): Use input_interactive_p instead of
input_from_terminal_p.
* defs.h (struct ui): Forward declare.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this.
* event-top.c (stdin_event_handler): Pass 0 as from_tty argument
to quit_command.
(command_handler): Adjust to per-UI stdin.
(handle_line_of_input): Adjust to per-UI stdin and use
input_interactive_p instead of ISATTY and input_from_terminal_p.
(gdb_readline_no_editing_callback): Adjust to per-UI stdin.
(command_line_handler): Always pass true as "from_tty" parameter
of handle_line_of_input and execute_command.
(async_sigterm_handler): Pass 0 as from_tty argument to
quit_command.
* inflow.c (interactive_mode, show_interactive_mode): Moved to ...
(gdb_has_a_terminal): Don't check interactive_mode here.
(_initialize_inflow): Don't install "set interactive-mode" here.
* main.c (captured_command_loop): Adjust to per-UI stdin.
* mi/mi-interp.c (mi_execute_command_wrapper): Adjust to per-UI
stdin.
* top.c (new_ui): Save the stdin stream and whether it's a tty.
(dont_repeat): Adjust to per-UI stdin.
(command_line_input): Adjust to per-UI stdin and to use
input_interactive_p.
(quit_force): Write history if any UI supports interactive input.
(interactive_mode, show_interactive_mode): Move here, from
inflow.c.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this, and check the "interactive_mode"
global instead of calling gdb_has_a_terminal.
(_initialize_top): Install "set interactive-mode" here.
* top.h (struct ui) <stdin_stream, input_interactive_p>: New
fields.
* utils.c (quit): Pass 0 as from_tty argument to quit_force.
(defaulted_query): Adjust to per-UI stdin and to use
input_interactive_p.

gdb/ChangeLog
gdb/cli/cli-script.c
gdb/defs.h
gdb/event-top.c
gdb/inflow.c
gdb/main.c
gdb/mi/mi-interp.c
gdb/top.c
gdb/top.h
gdb/utils.c

index 22b369dc2971a14453843c061320db5e576b03a9..ed1f53a888904f7baf6adc2cdca47ae6ca5cf038 100644 (file)
@@ -1,3 +1,44 @@
+2016-06-21  Pedro Alves  <palves@redhat.com>
+
+       * cli/cli-script.c (read_next_line): Adjust to per-UI stdin.
+       (read_command_lines): Use input_interactive_p instead of
+       input_from_terminal_p.
+       * defs.h (struct ui): Forward declare.
+       (input_from_terminal_p): Rename to ...
+       (input_interactive_p): ... this.
+       * event-top.c (stdin_event_handler): Pass 0 as from_tty argument
+       to quit_command.
+       (command_handler): Adjust to per-UI stdin.
+       (handle_line_of_input): Adjust to per-UI stdin and use
+       input_interactive_p instead of ISATTY and input_from_terminal_p.
+       (gdb_readline_no_editing_callback): Adjust to per-UI stdin.
+       (command_line_handler): Always pass true as "from_tty" parameter
+       of handle_line_of_input and execute_command.
+       (async_sigterm_handler): Pass 0 as from_tty argument to
+       quit_command.
+       * inflow.c (interactive_mode, show_interactive_mode): Moved to ...
+       (gdb_has_a_terminal): Don't check interactive_mode here.
+       (_initialize_inflow): Don't install "set interactive-mode" here.
+       * main.c (captured_command_loop): Adjust to per-UI stdin.
+       * mi/mi-interp.c (mi_execute_command_wrapper): Adjust to per-UI
+       stdin.
+       * top.c (new_ui): Save the stdin stream and whether it's a tty.
+       (dont_repeat): Adjust to per-UI stdin.
+       (command_line_input): Adjust to per-UI stdin and to use
+       input_interactive_p.
+       (quit_force): Write history if any UI supports interactive input.
+       (interactive_mode, show_interactive_mode): Move here, from
+       inflow.c.
+       (input_from_terminal_p): Rename to ...
+       (input_interactive_p): ... this, and check the "interactive_mode"
+       global instead of calling gdb_has_a_terminal.
+       (_initialize_top): Install "set interactive-mode" here.
+       * top.h (struct ui) <stdin_stream, input_interactive_p>: New
+       fields.
+       * utils.c (quit): Pass 0 as from_tty argument to quit_force.
+       (defaulted_query): Adjust to per-UI stdin and to use
+       input_interactive_p.
+
 2016-06-21  Pedro Alves  <palves@redhat.com>
 
        * event-top.c (stdin_event_handler): Don't quit gdb if it was a
index 0507c5515ca3cee16ac31e30fe62ae4bf6ceaf48..579d0a49a74e918a68a1f85caf37827985311a27 100644 (file)
@@ -935,12 +935,13 @@ read_next_line (void)
   struct ui *ui = current_ui;
   char *prompt_ptr, control_prompt[256];
   int i = 0;
+  int from_tty = ui->instream == ui->stdin_stream;
 
   if (control_level >= 254)
     error (_("Control nesting too deep!"));
 
   /* Set a prompt based on the nesting of the control commands.  */
-  if (ui->instream == stdin
+  if (from_tty
       || (ui->instream == 0 && deprecated_readline_hook != NULL))
     {
       for (i = 0; i < control_level; i++)
@@ -952,7 +953,7 @@ read_next_line (void)
   else
     prompt_ptr = NULL;
 
-  return command_line_input (prompt_ptr, ui->instream == stdin, "commands");
+  return command_line_input (prompt_ptr, from_tty, "commands");
 }
 
 /* Process one input line.  If the command is an "end", return such an
@@ -1256,7 +1257,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands,
 {
   struct command_line *head;
 
-  if (from_tty && input_from_terminal_p ())
+  if (from_tty && input_interactive_p (current_ui))
     {
       if (deprecated_readline_begin_hook)
        {
@@ -1287,7 +1288,8 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands,
       do_cleanups (old_chain);
     }
 
-  if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
+  if (from_tty && input_interactive_p (current_ui)
+      && deprecated_readline_end_hook)
     {
       (*deprecated_readline_end_hook) ();
     }
index ed513968523a16634dc9a9fdd325886ce6a5b49c..b81de46fee17c9a120620f63fdec94d2326c17f0 100644 (file)
@@ -324,7 +324,9 @@ extern char *command_line_input (const char *, int, char *);
 
 extern void print_prompt (void);
 
-extern int input_from_terminal_p (void);
+struct ui;
+
+extern int input_interactive_p (struct ui *);
 
 extern int info_verbose;
 
index 777823ef2ea1ff01fbe691768d1e6799f1da14b3..072ad2aceee65fbabbe265ae65cce040ef2e4c3e 100644 (file)
@@ -518,7 +518,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
        {
          /* If stdin died, we may as well kill gdb.  */
          printf_unfiltered (_("error detected on stdin\n"));
-         quit_command ((char *) 0, stdin == ui->instream);
+         quit_command ((char *) 0, 0);
        }
       else
        {
@@ -589,7 +589,7 @@ command_handler (char *command)
   struct cleanup *stat_chain;
   char *c;
 
-  if (ui->instream == stdin)
+  if (ui->instream == ui->stdin_stream)
     reinitialize_more_filter ();
 
   stat_chain = make_command_stats_cleanup (1);
@@ -599,7 +599,7 @@ command_handler (char *command)
     ;
   if (c[0] != '#')
     {
-      execute_command (command, ui->instream == stdin);
+      execute_command (command, ui->instream == ui->stdin_stream);
 
       /* Do any commands attached to breakpoint we stopped at.  */
       bpstat_do_actions ();
@@ -667,6 +667,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
                      char *rl, int repeat, char *annotation_suffix)
 {
   struct ui *ui = current_ui;
+  int from_tty = ui->instream == ui->stdin_stream;
   char *p1;
   char *cmd;
 
@@ -681,7 +682,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
      command, but leave ownership of memory to the buffer .  */
   cmd_line_buffer->used_size = 0;
 
-  if (annotation_level > 1 && ui->instream == stdin)
+  if (from_tty && annotation_level > 1)
     {
       printf_unfiltered (("\n\032\032post-"));
       puts_unfiltered (annotation_suffix);
@@ -698,8 +699,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
     }
 
   /* Do history expansion if that is wished.  */
-  if (history_expansion_p && ui->instream == stdin
-      && ISATTY (ui->instream))
+  if (history_expansion_p && from_tty && input_interactive_p (current_ui))
     {
       char *history_value;
       int expanded;
@@ -743,7 +743,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
      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' && input_from_terminal_p ())
+  if (*cmd != '\0' && from_tty && input_interactive_p (current_ui))
     gdb_add_history (cmd);
 
   /* Save into global buffer if appropriate.  */
@@ -772,8 +772,7 @@ command_line_handler (char *rl)
   struct ui *ui = current_ui;
   char *cmd;
 
-  cmd = handle_line_of_input (line_buffer, rl, ui->instream == stdin,
-                             "prompt");
+  cmd = handle_line_of_input (line_buffer, rl, 1, "prompt");
   if (cmd == (char *) EOF)
     {
       /* stdin closed.  The connection with the terminal is gone.
@@ -781,7 +780,7 @@ command_line_handler (char *rl)
         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", stdin == ui->instream);
+      execute_command ("quit", 1);
     }
   else if (cmd == NULL)
     {
@@ -838,7 +837,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
     {
       /* Read from stdin if we are executing a user defined command.
          This is the right thing for prompt_for_continue, at least.  */
-      c = fgetc (ui->instream ? ui->instream : stdin);
+      c = fgetc (ui->instream != NULL ? ui->instream : ui->stdin_stream);
 
       if (c == EOF)
        {
@@ -1086,7 +1085,7 @@ interruptible_select (int n,
 static void
 async_sigterm_handler (gdb_client_data arg)
 {
-  quit_force (NULL, stdin == current_ui->instream);
+  quit_force (NULL, 0);
 }
 
 /* See defs.h.  */
index 4c80dbd896b54238cb0d3a1e4afc0e60dfa78892..4cbcd5c74e691e8558c8088b2ad795c604006e51 100644 (file)
@@ -142,24 +142,6 @@ enum gdb_has_a_terminal_flag_enum
   }
 gdb_has_a_terminal_flag = have_not_checked;
 
-/* The value of the "interactive-mode" setting.  */
-static enum auto_boolean interactive_mode = AUTO_BOOLEAN_AUTO;
-
-/* Implement the "show interactive-mode" option.  */
-
-static void
-show_interactive_mode (struct ui_file *file, int from_tty,
-                       struct cmd_list_element *c,
-                       const char *value)
-{
-  if (interactive_mode == AUTO_BOOLEAN_AUTO)
-    fprintf_filtered (file, "Debugger's interactive mode "
-                           "is %s (currently %s).\n",
-                      value, gdb_has_a_terminal () ? "on" : "off");
-  else
-    fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
-}
-
 /* Set the initial tty state that is to be inherited by new inferiors.  */
 
 void
@@ -172,9 +154,6 @@ set_initial_gdb_ttystate (void)
 int
 gdb_has_a_terminal (void)
 {
-  if (interactive_mode != AUTO_BOOLEAN_AUTO)
-    return interactive_mode == AUTO_BOOLEAN_TRUE;
-
   switch (gdb_has_a_terminal_flag)
     {
     case yes:
@@ -899,20 +878,6 @@ _initialize_inflow (void)
   add_info ("terminal", term_info,
            _("Print inferior's saved terminal status."));
 
-  add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
-                                &interactive_mode, _("\
-Set whether GDB's standard input is a terminal."), _("\
-Show whether GDB's standard input is a terminal."), _("\
-If on, GDB assumes that standard input is a terminal.  In practice, it\n\
-means that GDB should wait for the user to answer queries associated to\n\
-commands entered at the command prompt.  If off, GDB assumes that standard\n\
-input is not a terminal, and uses the default answer to all queries.\n\
-If auto (the default), determine which mode to use based on the standard\n\
-input settings."),
-                        NULL,
-                        show_interactive_mode,
-                        &setlist, &showlist);
-
   terminal_is_ours = 1;
 
   /* OK, figure out whether we have job control.  If neither termios nor
index f4e5b2f4c3bc74f10e5a158e962975bf69e85c6c..947ed558a1f0445c363f5d884bc674307ac0f2f1 100644 (file)
@@ -334,7 +334,7 @@ captured_command_loop (void *data)
      error) we try to quit.  If the quit is aborted, catch_errors()
      which called this catch the signal and restart the command
      loop.  */
-  quit_command (NULL, ui->instream == stdin);
+  quit_command (NULL, ui->instream == ui->stdin_stream);
   return 1;
 }
 
index 76238ec8d4c50008063563dbeeba452f3249ce38..e3c7dbd2fe77b847d3f559cdb7805d3f61204bec 100644 (file)
@@ -286,7 +286,7 @@ mi_execute_command_wrapper (const char *cmd)
 {
   struct ui *ui = current_ui;
 
-  mi_execute_command (cmd, stdin == ui->instream);
+  mi_execute_command (cmd, ui->instream == ui->stdin_stream);
 }
 
 /* Observer for the synchronous_command_done notification.  */
index 5883875e8d4673170bbeec1d7b46a238653d59f5..7506c4577ce74a60609b01ca6da4f2e6b8367a74 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -259,12 +259,15 @@ new_ui (FILE *instream, FILE *outstream, FILE *errstream)
   ui = XCNEW (struct ui);
 
   ui->num = ++highest_ui_num;
+  ui->stdin_stream = instream;
   ui->instream = instream;
   ui->outstream = outstream;
   ui->errstream = errstream;
 
   ui->input_fd = fileno (ui->instream);
 
+  ui->input_interactive_p = ISATTY (ui->instream);
+
   ui->m_gdb_stdin = stdio_fileopen (ui->instream);
   ui->m_gdb_stdout = stdio_fileopen (ui->outstream);
   ui->m_gdb_stderr = stderr_fileopen (ui->errstream);
@@ -646,7 +649,7 @@ dont_repeat (void)
   /* If we aren't reading from standard input, we are saving the last
      thing read from stdin in line and don't want to delete it.  Null
      lines won't repeat here in any case.  */
-  if (ui->instream == stdin)
+  if (ui->instream == ui->stdin_stream)
     *saved_command_line = 0;
 }
 
@@ -1108,7 +1111,7 @@ gdb_safe_append_history (void)
 
    NULL is returned for end of file.
 
-   *If* the instream == stdin & stdin is a terminal, the line read is
+   *If* input is from an interactive stream (stdin), the line read is
    copied into the global 'saved_command_line' so that it can be
    repeated.
 
@@ -1123,12 +1126,13 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
   struct ui *ui = current_ui;
   const char *prompt = prompt_arg;
   char *cmd;
+  int from_tty = ui->instream == ui->stdin_stream;
 
   /* The annotation suffix must be non-NULL.  */
   if (annotation_suffix == NULL)
     annotation_suffix = "";
 
-  if (annotation_level > 1 && ui->instream == stdin)
+  if (from_tty && annotation_level > 1)
     {
       char *local_prompt;
 
@@ -1174,7 +1178,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
       if (source_file_name != NULL)
        ++source_line_number;
 
-      if (annotation_level > 1 && ui->instream == stdin)
+      if (from_tty && annotation_level > 1)
        {
          puts_unfiltered ("\n\032\032pre-");
          puts_unfiltered (annotation_suffix);
@@ -1182,11 +1186,15 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
        }
 
       /* Don't use fancy stuff if not talking to stdin.  */
-      if (deprecated_readline_hook && input_from_terminal_p ())
+      if (deprecated_readline_hook
+         && from_tty
+         && input_interactive_p (current_ui))
        {
          rl = (*deprecated_readline_hook) (prompt);
        }
-      else if (command_editing_p && input_from_terminal_p ())
+      else if (command_editing_p
+              && from_tty
+              && input_interactive_p (current_ui))
        {
          rl = gdb_readline_wrapper (prompt);
        }
@@ -1561,9 +1569,25 @@ quit_force (char *args, int from_tty)
   /* Save the history information if it is appropriate to do so.  */
   TRY
     {
-      if (write_history_p && history_filename
-         && input_from_terminal_p ())
-       gdb_safe_append_history ();
+      if (write_history_p && history_filename)
+       {
+         struct ui *ui;
+         int save = 0;
+
+         /* History is currently shared between all UIs.  If there's
+            any UI with a terminal, save history.  */
+         ALL_UIS (ui)
+           {
+             if (input_interactive_p (ui))
+               {
+                 save = 1;
+                 break;
+               }
+           }
+
+         if (save)
+           gdb_safe_append_history ();
+       }
     }
   CATCH (ex, RETURN_MASK_ALL)
     {
@@ -1585,27 +1609,36 @@ quit_force (char *args, int from_tty)
   exit (exit_code);
 }
 
-/* Returns whether GDB is running on a terminal and input is
-   currently coming from that terminal.  */
+/* The value of the "interactive-mode" setting.  */
+static enum auto_boolean interactive_mode = AUTO_BOOLEAN_AUTO;
 
-int
-input_from_terminal_p (void)
+/* Implement the "show interactive-mode" option.  */
+
+static void
+show_interactive_mode (struct ui_file *file, int from_tty,
+                       struct cmd_list_element *c,
+                       const char *value)
 {
-  struct ui *ui = current_ui;
+  if (interactive_mode == AUTO_BOOLEAN_AUTO)
+    fprintf_filtered (file, "Debugger's interactive mode "
+                           "is %s (currently %s).\n",
+                      value, gdb_has_a_terminal () ? "on" : "off");
+  else
+    fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
+}
+
+/* Returns whether GDB is running on an interactive terminal.  */
 
+int
+input_interactive_p (struct ui *ui)
+{
   if (batch_flag)
     return 0;
 
-  if (gdb_has_a_terminal () && ui->instream == stdin)
-    return 1;
-
-  /* If INSTREAM is unset, and we are not in a user command, we
-     must be in Insight.  That's like having a terminal, for our
-     purposes.  */
-  if (ui->instream == NULL && !in_user_command)
-    return 1;
+  if (interactive_mode != AUTO_BOOLEAN_AUTO)
+    return interactive_mode == AUTO_BOOLEAN_TRUE;
 
-  return 0;
+  return ui->input_interactive_p;
 }
 \f
 static void
@@ -2013,6 +2046,20 @@ When set, GDB uses the specified path to search for data files."),
                            set_gdb_datadir, show_gdb_datadir,
                            &setlist,
                            &showlist);
+
+  add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
+                                &interactive_mode, _("\
+Set whether GDB's standard input is a terminal."), _("\
+Show whether GDB's standard input is a terminal."), _("\
+If on, GDB assumes that standard input is a terminal.  In practice, it\n\
+means that GDB should wait for the user to answer queries associated to\n\
+commands entered at the command prompt.  If off, GDB assumes that standard\n\
+input is not a terminal, and uses the default answer to all queries.\n\
+If auto (the default), determine which mode to use based on the standard\n\
+input settings."),
+                        NULL,
+                        show_interactive_mode,
+                        &setlist, &showlist);
 }
 
 void
index 7fbd187fa92fa4062dff45370cd44fbba486b47a..64f7211650183a46a099dd47f4029ba6c3d39426 100644 (file)
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -98,6 +98,9 @@ struct ui
      currently active.  */
   int secondary_prompt_depth;
 
+  /* The UI's stdin.  Set to stdin for the main UI.  */
+  FILE *stdin_stream;
+
   /* stdio stream that command input is being read from.  Set to stdin
      normally.  Set by source_command to the file we are sourcing.
      Set to NULL if we are executing a user-defined command or
@@ -112,6 +115,11 @@ struct ui
      it with the event loop.  */
   int input_fd;
 
+  /* Whether ISATTY returns true on input_fd.  Cached here because
+     quit_force needs to know this _after_ input_fd might be
+     closed.  */
+  int input_interactive_p;
+
   /* See enum prompt_state's description.  */
   enum prompt_state prompt_state;
 
index 78d2e984b86ad8d3e26c131efb64833bd13b9a1e..c70e99cea4924a3dc5093b3d340db29a03b85784 100644 (file)
@@ -1052,7 +1052,7 @@ quit (void)
   if (sync_quit_force_run)
     {
       sync_quit_force_run = 0;
-      quit_force (NULL, stdin == ui->instream);
+      quit_force (NULL, 0);
     }
 
 #ifdef __MSDOS__
@@ -1271,7 +1271,8 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
      question we're asking, and then answer the default automatically.  This
      way, important error messages don't get lost when talking to GDB
      over a pipe.  */
-  if (! input_from_terminal_p ())
+  if (current_ui->instream != current_ui->stdin_stream
+      || !input_interactive_p (current_ui))
     {
       target_terminal_ours_for_output ();
       wrap_here ("");