* win32-nat.c (psapi_module_handle): Remove static.
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index b7ef75d65694be3543aa0fdfa85e725da37d2286..e8ac46a8ac44bc22938b42728de4c98dd1cddc69 100644 (file)
@@ -1,14 +1,14 @@
 /* Memory-access and commands for "inferior" process, for GDB.
 
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include <signal.h>
@@ -47,6 +45,9 @@
 #include "solib.h"
 #include <ctype.h>
 #include "gdb_assert.h"
+#include "observer.h"
+#include "target-descriptions.h"
+#include "user-regs.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -66,7 +67,7 @@ void interrupt_target_command (char *args, int from_tty);
 
 static void nofp_registers_info (char *, int);
 
-static void print_return_value (int struct_return, struct type *value_type);
+static void print_return_value (struct type *value_type);
 
 static void finish_command_continuation (struct continuation_arg *);
 
@@ -136,7 +137,7 @@ static char **inferior_argv;
 
 /* File name for default use for standard in/out in the inferior.  */
 
-char *inferior_io_terminal;
+static char *inferior_io_terminal;
 
 /* Pid of our debugged inferior, or 0 if no inferior now.
    Since various parts of infrun.c test this to see whether there is a program
@@ -203,6 +204,24 @@ struct gdb_environ *inferior_environ;
 \f
 /* Accessor routines. */
 
+void 
+set_inferior_io_terminal (const char *terminal_name)
+{
+  if (inferior_io_terminal)
+    xfree (inferior_io_terminal);
+
+  if (!terminal_name)
+    inferior_io_terminal = NULL;
+  else
+    inferior_io_terminal = savestring (terminal_name, strlen (terminal_name));
+}
+
+const char *
+get_inferior_io_terminal (void)
+{
+  return inferior_io_terminal;
+}
+
 char *
 get_inferior_args (void)
 {
@@ -376,7 +395,48 @@ tty_command (char *file, int from_tty)
   if (file == 0)
     error_no_arg (_("terminal name for running target process"));
 
-  inferior_io_terminal = savestring (file, strlen (file));
+  set_inferior_io_terminal (file);
+}
+
+/* Common actions to take after creating any sort of inferior, by any
+   means (running, attaching, connecting, et cetera).  The target
+   should be stopped.  */
+
+void
+post_create_inferior (struct target_ops *target, int from_tty)
+{
+  /* Be sure we own the terminal in case write operations are performed.  */ 
+  target_terminal_ours ();
+
+  /* If the target hasn't taken care of this already, do it now.
+     Targets which need to access registers during to_open,
+     to_create_inferior, or to_attach should do it earlier; but many
+     don't need to.  */
+  target_find_description ();
+
+  if (exec_bfd)
+    {
+      /* Sometimes the platform-specific hook loads initial shared
+        libraries, and sometimes it doesn't.  Try to do so first, so
+        that we can add them with the correct value for FROM_TTY.
+        If we made all the inferior hook methods consistent,
+        this call could be removed.  */
+#ifdef SOLIB_ADD
+      SOLIB_ADD (NULL, from_tty, target, auto_solib_add);
+#else
+      solib_add (NULL, from_tty, target, auto_solib_add);
+#endif
+
+      /* Create the hooks to handle shared library load and unload
+        events.  */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+      SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
+#else
+      solib_create_inferior_hook ();
+#endif
+    }
+
+  observer_notify_inferior_created (target, from_tty);
 }
 
 /* Kill the inferior if already running.  This function is designed
@@ -415,10 +475,14 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
   kill_if_already_running (from_tty);
   clear_breakpoint_hit_counts ();
 
+  /* Clean up any leftovers from other runs.  Some other things from
+     this function should probably be moved into target_pre_inferior.  */
+  target_pre_inferior (from_tty);
+
   /* Purge old solib objfiles. */
   objfile_purge_solibs ();
 
-  do_run_cleanups (NULL);
+  clear_solib ();
 
   /* The comment here used to read, "The exec file is re-read every
      time we do a generic_mourn_inferior, so we just have to worry
@@ -492,6 +556,13 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
      the value now.  */
   target_create_inferior (exec_file, get_inferior_args (),
                          environ_vector (inferior_environ), from_tty);
+
+  /* Pass zero for FROM_TTY, because at this point the "run" command
+     has done its thing; now we are setting up the running program.  */
+  post_create_inferior (&current_target, 0);
+
+  /* Start the target running.  */
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
 }
 
 
@@ -553,23 +624,27 @@ continue_command (char *proc_count_exp, int from_tty)
   if (proc_count_exp != NULL)
     {
       bpstat bs = stop_bpstat;
-      int num = bpstat_num (&bs);
-      if (num == 0 && from_tty)
+      int num, stat;
+      int stopped = 0;
+
+      while ((stat = bpstat_num (&bs, &num)) != 0)
+       if (stat > 0)
+         {
+           set_ignore_count (num,
+                             parse_and_eval_long (proc_count_exp) - 1,
+                             from_tty);
+           /* set_ignore_count prints a message ending with a period.
+              So print two spaces before "Continuing.".  */
+           if (from_tty)
+             printf_filtered ("  ");
+           stopped = 1;
+         }
+
+      if (!stopped && from_tty)
        {
          printf_filtered
            ("Not stopped at any breakpoint; argument ignored.\n");
        }
-      while (num != 0)
-       {
-         set_ignore_count (num,
-                           parse_and_eval_long (proc_count_exp) - 1,
-                           from_tty);
-         /* set_ignore_count prints a message ending with a period.
-            So print two spaces before "Continuing.".  */
-         if (from_tty)
-           printf_filtered ("  ");
-         num = bpstat_num (&bs);
-       }
     }
 
   if (from_tty)
@@ -1086,13 +1161,14 @@ advance_command (char *arg, int from_tty)
 /* Print the result of a function at the end of a 'finish' command.  */
 
 static void
-print_return_value (int struct_return, struct type *value_type)
+print_return_value (struct type *value_type)
 {
   struct gdbarch *gdbarch = current_gdbarch;
   struct cleanup *old_chain;
   struct ui_stream *stb;
   struct value *value;
 
+  CHECK_TYPEDEF (value_type);
   gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
 
   /* FIXME: 2003-09-27: When returning from a nested inferior function
@@ -1106,9 +1182,9 @@ print_return_value (int struct_return, struct type *value_type)
     {
     case RETURN_VALUE_REGISTER_CONVENTION:
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
+    case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
       value = allocate_value (value_type);
-      CHECK_TYPEDEF (value_type);
-      gdbarch_return_value (current_gdbarch, value_type, stop_registers,
+      gdbarch_return_value (gdbarch, value_type, stop_registers,
                            value_contents_raw (value), NULL);
       break;
     case RETURN_VALUE_STRUCT_CONVENTION:
@@ -1165,25 +1241,14 @@ finish_command_continuation (struct continuation_arg *arg)
       && function != NULL)
     {
       struct type *value_type;
-      int struct_return;
-      int gcc_compiled;
 
       value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
       if (!value_type)
        internal_error (__FILE__, __LINE__,
                        _("finish_command: function has no target type"));
 
-      if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
-       {
-         do_exec_cleanups (cleanups);
-         return;
-       }
-
-      CHECK_TYPEDEF (value_type);
-      gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
-      struct_return = using_struct_return (value_type, gcc_compiled);
-
-      print_return_value (struct_return, value_type); 
+      if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+       print_return_value (value_type); 
     }
 
   do_exec_cleanups (cleanups);
@@ -1225,10 +1290,8 @@ finish_command (char *arg, int from_tty)
     error (_("The \"finish\" command does not take any arguments."));
   if (!target_has_execution)
     error (_("The program is not running."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
 
-  frame = get_prev_frame (deprecated_selected_frame);
+  frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
   if (frame == 0)
     error (_("\"finish\" not meaningful in the outermost frame."));
 
@@ -1246,7 +1309,7 @@ finish_command (char *arg, int from_tty)
 
   /* Find the function we will return from.  */
 
-  function = find_pc_function (get_frame_pc (deprecated_selected_frame));
+  function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
 
   /* Print info on the selected frame, including level number but not
      source.  */
@@ -1290,23 +1353,14 @@ finish_command (char *arg, int from_tty)
          && function != NULL)
        {
          struct type *value_type;
-         int struct_return;
-         int gcc_compiled;
 
          value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
          if (!value_type)
            internal_error (__FILE__, __LINE__,
                            _("finish_command: function has no target type"));
 
-         /* FIXME: Shouldn't we do the cleanups before returning?  */
-         if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
-           return;
-
-         CHECK_TYPEDEF (value_type);
-         gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
-         struct_return = using_struct_return (value_type, gcc_compiled);
-
-         print_return_value (struct_return, value_type); 
+         if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+           print_return_value (value_type); 
        }
 
       do_cleanups (old_chain);
@@ -1318,7 +1372,8 @@ static void
 program_info (char *args, int from_tty)
 {
   bpstat bs = stop_bpstat;
-  int num = bpstat_num (&bs);
+  int num;
+  int stat = bpstat_num (&bs, &num);
 
   if (!target_has_execution)
     {
@@ -1331,20 +1386,20 @@ program_info (char *args, int from_tty)
                   hex_string ((unsigned long) stop_pc));
   if (stop_step)
     printf_filtered (_("It stopped after being stepped.\n"));
-  else if (num != 0)
+  else if (stat != 0)
     {
       /* There may be several breakpoints in the same place, so this
          isn't as strange as it seems.  */
-      while (num != 0)
+      while (stat != 0)
        {
-         if (num < 0)
+         if (stat < 0)
            {
              printf_filtered (_("\
 It stopped at a breakpoint that has since been deleted.\n"));
            }
          else
            printf_filtered (_("It stopped at breakpoint %d.\n"), num);
-         num = bpstat_num (&bs);
+         stat = bpstat_num (&bs, &num);
        }
     }
   else if (stop_signal != TARGET_SIGNAL_0)
@@ -1523,8 +1578,9 @@ default_print_registers_info (struct gdbarch *gdbarch,
                              int regnum, int print_all)
 {
   int i;
-  const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
-  char buffer[MAX_REGISTER_SIZE];
+  const int numregs = gdbarch_num_regs (gdbarch)
+                     + gdbarch_num_pseudo_regs (gdbarch);
+  gdb_byte buffer[MAX_REGISTER_SIZE];
 
   for (i = 0; i < numregs; i++)
     {
@@ -1551,11 +1607,13 @@ default_print_registers_info (struct gdbarch *gdbarch,
 
       /* If the register name is empty, it is undefined for this
          processor, so don't display anything.  */
-      if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+      if (gdbarch_register_name (gdbarch, i) == NULL
+         || *(gdbarch_register_name (gdbarch, i)) == '\0')
        continue;
 
-      fputs_filtered (REGISTER_NAME (i), file);
-      print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), file);
+      fputs_filtered (gdbarch_register_name (gdbarch, i), file);
+      print_spaces_filtered (15 - strlen (gdbarch_register_name
+                                         (gdbarch, i)), file);
 
       /* Get the data in raw format.  */
       if (! frame_register_read (frame, i, buffer))
@@ -1566,21 +1624,21 @@ default_print_registers_info (struct gdbarch *gdbarch,
 
       /* If virtual format is floating, print it that way, and in raw
          hex.  */
-      if (TYPE_CODE (register_type (current_gdbarch, i)) == TYPE_CODE_FLT)
+      if (TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_FLT)
        {
          int j;
 
-         val_print (register_type (current_gdbarch, i), buffer, 0, 0,
+         val_print (register_type (gdbarch, i), buffer, 0, 0,
                     file, 0, 1, 0, Val_pretty_default);
 
          fprintf_filtered (file, "\t(raw 0x");
-         for (j = 0; j < register_size (current_gdbarch, i); j++)
+         for (j = 0; j < register_size (gdbarch, i); j++)
            {
              int idx;
-             if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+             if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
                idx = j;
              else
-               idx = register_size (current_gdbarch, i) - 1 - j;
+               idx = register_size (gdbarch, i) - 1 - j;
              fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
            }
          fprintf_filtered (file, ")");
@@ -1588,14 +1646,14 @@ default_print_registers_info (struct gdbarch *gdbarch,
       else
        {
          /* Print the register in hex.  */
-         val_print (register_type (current_gdbarch, i), buffer, 0, 0,
+         val_print (register_type (gdbarch, i), buffer, 0, 0,
                     file, 'x', 1, 0, Val_pretty_default);
           /* If not a vector register, print it also according to its
              natural format.  */
-         if (TYPE_VECTOR (register_type (current_gdbarch, i)) == 0)
+         if (TYPE_VECTOR (register_type (gdbarch, i)) == 0)
            {
              fprintf_filtered (file, "\t");
-             val_print (register_type (current_gdbarch, i), buffer, 0, 0,
+             val_print (register_type (gdbarch, i), buffer, 0, 0,
                         file, 0, 1, 0, Val_pretty_default);
            }
        }
@@ -1607,18 +1665,20 @@ default_print_registers_info (struct gdbarch *gdbarch,
 void
 registers_info (char *addr_exp, int fpregs)
 {
+  struct frame_info *frame;
+  struct gdbarch *gdbarch;
   int regnum, numregs;
   char *end;
 
   if (!target_has_registers)
     error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
+  frame = get_selected_frame (NULL);
+  gdbarch = get_frame_arch (frame);
 
   if (!addr_exp)
     {
-      gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                   deprecated_selected_frame, -1, fpregs);
+      gdbarch_print_registers_info (gdbarch, gdb_stdout,
+                                   frame, -1, fpregs);
       return;
     }
 
@@ -1646,31 +1706,46 @@ registers_info (char *addr_exp, int fpregs)
       while ((*addr_exp) != '\0' && !isspace ((*addr_exp)))
        addr_exp++;
       end = addr_exp;
-      
+
       /* Figure out what we've found and display it.  */
 
       /* A register name?  */
       {
-       int regnum = frame_map_name_to_regnum (deprecated_selected_frame,
-                                              start, end - start);
+       int regnum = frame_map_name_to_regnum (frame, start, end - start);
        if (regnum >= 0)
          {
-           gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                         deprecated_selected_frame, regnum, fpregs);
+           /* User registers lie completely outside of the range of
+              normal registers.  Catch them early so that the target
+              never sees them.  */
+           if (regnum >= gdbarch_num_regs (gdbarch)
+                         + gdbarch_num_pseudo_regs (gdbarch))
+             {
+               struct value *val = value_of_user_reg (regnum, frame);
+
+               printf_filtered ("%s: ", start);
+               print_scalar_formatted (value_contents (val),
+                                       check_typedef (value_type (val)),
+                                       'x', 0, gdb_stdout);
+               printf_filtered ("\n");
+             }
+           else
+             gdbarch_print_registers_info (gdbarch, gdb_stdout,
+                                           frame, regnum, fpregs);
            continue;
          }
       }
-       
+
       /* A register number?  (how portable is this one?).  */
       {
        char *endptr;
        int regnum = strtol (start, &endptr, 0);
        if (endptr == end
            && regnum >= 0
-           && regnum < NUM_REGS + NUM_PSEUDO_REGS)
+           && regnum < gdbarch_num_regs (gdbarch)
+                       + gdbarch_num_pseudo_regs (gdbarch))
          {
-           gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                         deprecated_selected_frame, regnum, fpregs);
+           gdbarch_print_registers_info (gdbarch, gdb_stdout,
+                                         frame, regnum, fpregs);
            continue;
          }
       }
@@ -1678,9 +1753,9 @@ registers_info (char *addr_exp, int fpregs)
       /* A register group?  */
       {
        struct reggroup *group;
-       for (group = reggroup_next (current_gdbarch, NULL);
+       for (group = reggroup_next (gdbarch, NULL);
             group != NULL;
-            group = reggroup_next (current_gdbarch, group))
+            group = reggroup_next (gdbarch, group))
          {
            /* Don't bother with a length check.  Should the user
               enter a short register group name, go with the first
@@ -1691,12 +1766,14 @@ registers_info (char *addr_exp, int fpregs)
        if (group != NULL)
          {
            int regnum;
-           for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+           for (regnum = 0;
+                regnum < gdbarch_num_regs (gdbarch)
+                         + gdbarch_num_pseudo_regs (gdbarch);
+                regnum++)
              {
-               if (gdbarch_register_reggroup_p (current_gdbarch, regnum,
-                                                group))
-                 gdbarch_print_registers_info (current_gdbarch,
-                                               gdb_stdout, deprecated_selected_frame,
+               if (gdbarch_register_reggroup_p (gdbarch, regnum, group))
+                 gdbarch_print_registers_info (gdbarch,
+                                               gdb_stdout, frame,
                                                regnum, fpregs);
              }
            continue;
@@ -1724,11 +1801,6 @@ static void
 print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
                   struct frame_info *frame, const char *args)
 {
-  if (!target_has_registers)
-    error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
-
   if (gdbarch_print_vector_info_p (gdbarch))
     gdbarch_print_vector_info (gdbarch, file, frame, args);
   else
@@ -1736,7 +1808,10 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
       int regnum;
       int printed_something = 0;
 
-      for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+      for (regnum = 0;
+          regnum < gdbarch_num_regs (gdbarch)
+                   + gdbarch_num_pseudo_regs (gdbarch);
+          regnum++)
        {
          if (gdbarch_register_reggroup_p (gdbarch, regnum, vector_reggroup))
            {
@@ -1752,7 +1827,11 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
 static void
 vector_info (char *args, int from_tty)
 {
-  print_vector_info (current_gdbarch, gdb_stdout, deprecated_selected_frame, args);
+  if (!target_has_registers)
+    error (_("The program has no registers now."));
+
+  print_vector_info (current_gdbarch, gdb_stdout,
+                    get_selected_frame (NULL), args);
 }
 \f
 
@@ -1788,10 +1867,14 @@ attach_command (char *args, int from_tty)
        error (_("Not killed."));
     }
 
+  /* Clean up any leftovers from other runs.  Some other things from
+     this function should probably be moved into target_pre_inferior.  */
+  target_pre_inferior (from_tty);
+
   /* Clear out solib state. Otherwise the solib state of the previous
      inferior might have survived and is entirely wrong for the new
-     target.  This has been observed on Linux using glibc 2.3. How to
-     reproduce:
+     target.  This has been observed on GNU/Linux using glibc 2.3. How
+     to reproduce:
 
      bash$ ./foo&
      [1] 4711
@@ -1804,11 +1887,7 @@ attach_command (char *args, int from_tty)
      (gdb) attach 4712
      Cannot access memory at address 0xdeadbeef
   */
-#ifdef CLEAR_SOLIB
-      CLEAR_SOLIB ();
-#else
-      clear_solib ();
-#endif
+  clear_solib ();
 
   target_attach (args, from_tty);
 
@@ -1864,18 +1943,12 @@ attach_command (char *args, int from_tty)
       reread_symbols ();
     }
 
-#ifdef SOLIB_ADD
-  /* Add shared library symbols from the newly attached process, if any.  */
-  SOLIB_ADD ((char *) 0, from_tty, &current_target, auto_solib_add);
-#else
-  solib_add (NULL, from_tty, &current_target, auto_solib_add);
-#endif
-  re_enable_breakpoints_in_shlibs ();
-
   /* Take any necessary post-attaching actions for this platform.
    */
   target_post_attach (PIDGET (inferior_ptid));
 
+  post_create_inferior (&current_target, from_tty);
+
   /* Install inferior's terminal modes.  */
   target_terminal_inferior ();
 
@@ -1944,11 +2017,6 @@ static void
 print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
                  struct frame_info *frame, const char *args)
 {
-  if (!target_has_registers)
-    error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
-
   if (gdbarch_print_float_info_p (gdbarch))
     gdbarch_print_float_info (gdbarch, file, frame, args);
   else
@@ -1956,7 +2024,10 @@ print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
       int regnum;
       int printed_something = 0;
 
-      for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+      for (regnum = 0;
+          regnum < gdbarch_num_regs (gdbarch)
+                   + gdbarch_num_pseudo_regs (gdbarch);
+          regnum++)
        {
          if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
            {
@@ -1973,8 +2044,11 @@ No floating-point info available for this processor.\n");
 static void
 float_info (char *args, int from_tty)
 {
+  if (!target_has_registers)
+    error (_("The program has no registers now."));
+
   print_float_info (current_gdbarch, gdb_stdout, 
-                   deprecated_selected_frame, args);
+                   get_selected_frame (NULL), args);
 }
 \f
 static void
@@ -1988,11 +2062,15 @@ unset_command (char *args, int from_tty)
 void
 _initialize_infcmd (void)
 {
-  struct cmd_list_element *c;
+  struct cmd_list_element *c = NULL;
 
-  c = add_com ("tty", class_run, tty_command,
-              _("Set terminal for future runs of program being debugged."));
-  set_cmd_completer (c, filename_completer);
+  /* add the filename of the terminal connected to inferior I/O */
+  add_setshow_filename_cmd ("inferior-tty", class_run,
+                           &inferior_io_terminal, _("\
+Set terminal for future runs of program being debugged."), _("\
+Show terminal for future runs of program being debugged."), _("\
+Usage: set inferior-tty /dev/pts/1"), NULL, NULL, &setlist, &showlist);
+  add_com_alias ("tty", "set inferior-tty", class_alias, 0);
 
   add_setshow_optional_filename_cmd ("args", class_run,
                                     &inferior_args, _("\
@@ -2058,10 +2136,11 @@ directory, or (if not found there) using the source file search path\n\
 (see the \"directory\" command).  You can also use the \"file\" command\n\
 to specify the program, and to load its symbol table."));
 
-  add_com ("detach", class_run, detach_command, _("\
+  add_prefix_cmd ("detach", class_run, detach_command, _("\
 Detach a process or file previously attached.\n\
 If a process, it is no longer traced, and it continues its execution.  If\n\
-you were debugging a file, the file is closed and gdb no longer accesses it."));
+you were debugging a file, the file is closed and gdb no longer accesses it."),
+                 &detachlist, "detach ", 0, &cmdlist);
 
   add_com ("disconnect", class_run, disconnect_command, _("\
 Disconnect from a target.\n\
This page took 0.041426 seconds and 4 git commands to generate.