* ppc-linux-tdep.c (ELF_NGREG, ELF_NFPREG, ELF_NVRREG)
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index 5229fe1d5146c350073c31768be40e08f0222e59..83267ad9ab2934d53519d9174ee975edddc00882 100644 (file)
@@ -1,6 +1,6 @@
 /* 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
+   1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "symfile.h"
 #include "objfiles.h"
 #include "completer.h"
-#ifdef UI_OUT
 #include "ui-out.h"
-#endif
 #include "event-top.h"
 #include "parser-defs.h"
+#include "regcache.h"
 
 /* Functions exported for general use: */
 
@@ -123,6 +122,12 @@ static void breakpoint_auto_delete_contents (PTR);
 
 static char *inferior_args;
 
+/* The inferior arguments as a vector.  If INFERIOR_ARGC is nonzero,
+   then we must compute INFERIOR_ARGS from this (via the target).  */
+
+static int inferior_argc;
+static char **inferior_argv;
+
 /* File name for default use for standard in/out in the inferior.  */
 
 char *inferior_io_terminal;
@@ -199,6 +204,19 @@ struct environ *inferior_environ;
 char *
 get_inferior_args (void)
 {
+  if (inferior_argc != 0)
+    {
+      char *n, *old;
+
+      n = gdbarch_construct_inferior_arguments (current_gdbarch,
+                                               inferior_argc, inferior_argv);
+      old = set_inferior_args (n);
+      xfree (old);
+    }
+
+  if (inferior_args == NULL)
+    inferior_args = xstrdup ("");
+
   return inferior_args;
 }
 
@@ -208,10 +226,108 @@ set_inferior_args (char *newargs)
   char *saved_args = inferior_args;
 
   inferior_args = newargs;
+  inferior_argc = 0;
+  inferior_argv = 0;
 
   return saved_args;
 }
 
+void
+set_inferior_args_vector (int argc, char **argv)
+{
+  inferior_argc = argc;
+  inferior_argv = argv;
+}
+
+/* Notice when `set args' is run.  */
+static void
+notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
+{
+  inferior_argc = 0;
+  inferior_argv = 0;
+}
+
+/* Notice when `show args' is run.  */
+static void
+notice_args_read (char *args, int from_tty, struct cmd_list_element *c)
+{
+  /* Might compute the value.  */
+  get_inferior_args ();
+}
+
+\f
+/* Compute command-line string given argument vector.  This does the
+   same shell processing as fork_inferior.  */
+/* ARGSUSED */
+char *
+construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv)
+{
+  char *result;
+
+  if (STARTUP_WITH_SHELL)
+    {
+      /* This holds all the characters considered special to the
+        typical Unix shells.  We include `^' because the SunOS
+        /bin/sh treats it as a synonym for `|'.  */
+      char *special = "\"!#$&*()\\|[]{}<>?'\"`~^; \t\n";
+      int i;
+      int length = 0;
+      char *out, *cp;
+
+      /* We over-compute the size.  It shouldn't matter.  */
+      for (i = 0; i < argc; ++i)
+       length += 2 * strlen (argv[i]) + 1;
+
+      result = (char *) xmalloc (length);
+      out = result;
+
+      for (i = 0; i < argc; ++i)
+       {
+         if (i > 0)
+           *out++ = ' ';
+
+         for (cp = argv[i]; *cp; ++cp)
+           {
+             if (strchr (special, *cp) != NULL)
+               *out++ = '\\';
+             *out++ = *cp;
+           }
+       }
+      *out = '\0';
+    }
+  else
+    {
+      /* In this case we can't handle arguments that contain spaces,
+        tabs, or newlines -- see breakup_args().  */
+      int i;
+      int length = 0;
+
+      for (i = 0; i < argc; ++i)
+       {
+         char *cp = strchr (argv[i], ' ');
+         if (cp == NULL)
+           cp = strchr (argv[i], '\t');
+         if (cp == NULL)
+           cp = strchr (argv[i], '\n');
+         if (cp != NULL)
+           error ("can't handle command-line argument containing whitespace");
+         length += strlen (argv[i]) + 1;
+       }
+
+      result = (char *) xmalloc (length);
+      result[0] = '\0';
+      for (i = 0; i < argc; ++i)
+       {
+         if (i > 0)
+           strcat (result, " ");
+         strcat (result, argv[i]);
+       }
+    }
+
+  return result;
+}
+\f
+
 /* This function detects whether or not a '&' character (indicating
    background execution) has been added as *the last* of the arguments ARGS
    of a command. If it has, it removes it and returns 1. Otherwise it
@@ -274,17 +390,23 @@ Start it from the beginning? "))
 
   clear_breakpoint_hit_counts ();
 
-  exec_file = (char *) get_exec_file (0);
-
   /* Purge old solib objfiles. */
   objfile_purge_solibs ();
 
   do_run_cleanups (NULL);
 
-  /* The exec file is re-read every time we do a generic_mourn_inferior, so
-     we just have to worry about the symbol file.  */
+  /* 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
+     about the symbol file."  The `generic_mourn_inferior' function
+     gets called whenever the program exits.  However, suppose the
+     program exits, and *then* the executable file changes?  We need
+     to check again here.  Since reopen_exec_file doesn't do anything
+     if the timestamp hasn't changed, I don't see the harm.  */
+  reopen_exec_file ();
   reread_symbols ();
 
+  exec_file = (char *) get_exec_file (0);
+
   /* We keep symbols from add-symbol-file, on the grounds that the
      user might want to add some symbols before running the program
      (right?).  But sometimes (dynamic loading where the user manually
@@ -325,27 +447,21 @@ Start it from the beginning? "))
 
   if (from_tty)
     {
-#ifdef UI_OUT
       ui_out_field_string (uiout, NULL, "Starting program");
       ui_out_text (uiout, ": ");
       if (exec_file)
        ui_out_field_string (uiout, "execfile", exec_file);
       ui_out_spaces (uiout, 1);
-      ui_out_field_string (uiout, "infargs", inferior_args);
+      /* We call get_inferior_args() because we might need to compute
+        the value now.  */
+      ui_out_field_string (uiout, "infargs", get_inferior_args ());
       ui_out_text (uiout, "\n");
       ui_out_flush (uiout);
-#else
-      puts_filtered ("Starting program: ");
-      if (exec_file)
-       puts_filtered (exec_file);
-      puts_filtered (" ");
-      puts_filtered (inferior_args);
-      puts_filtered ("\n");
-      gdb_flush (gdb_stdout);
-#endif
     }
 
-  target_create_inferior (exec_file, inferior_args,
+  /* We call get_inferior_args() because we might need to compute
+     the value now.  */
+  target_create_inferior (exec_file, get_inferior_args (),
                          environ_vector (inferior_environ));
 }
 
@@ -854,7 +970,7 @@ breakpoint_auto_delete_contents (PTR arg)
    will eventually be popped when we do hit the dummy end breakpoint).  */
 
 int
-run_stack_dummy (CORE_ADDR addr, char *buffer)
+run_stack_dummy (CORE_ADDR addr, struct regcache *buffer)
 {
   struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
   int saved_async = 0;
@@ -927,8 +1043,7 @@ run_stack_dummy (CORE_ADDR addr, char *buffer)
     return 2;
 
   /* On normal return, the stack dummy has been popped already.  */
-
-  memcpy (buffer, stop_registers, REGISTER_BYTES);
+  regcache_cpy_no_passthrough (buffer, stop_registers);
   return 0;
 }
 \f
@@ -1023,15 +1138,12 @@ until_command (char *arg, int from_tty)
 static void
 print_return_value (int structure_return, struct type *value_type)
 {
-  register value_ptr value;
-#ifdef UI_OUT
+  struct value *value;
   static struct ui_stream *stb = NULL;
-#endif /* UI_OUT */
 
   if (!structure_return)
     {
       value = value_being_returned (value_type, stop_registers, structure_return);
-#ifdef UI_OUT
       stb = ui_out_stream_new (uiout);
       ui_out_text (uiout, "Value returned is ");
       ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
@@ -1039,11 +1151,6 @@ print_return_value (int structure_return, struct type *value_type)
       value_print (value, stb->stream, 0, Val_no_prettyprint);
       ui_out_field_stream (uiout, "return-value", stb);
       ui_out_text (uiout, "\n");
-#else /* UI_OUT */
-      printf_filtered ("Value returned is $%d = ", record_latest_value (value));
-      value_print (value, gdb_stdout, 0, Val_no_prettyprint);
-      printf_filtered ("\n");
-#endif /* UI_OUT */
     }
   else
     {
@@ -1052,18 +1159,12 @@ print_return_value (int structure_return, struct type *value_type)
         initiate the call, as opposed to the call_function_by_hand case */
 #ifdef VALUE_RETURNED_FROM_STACK
       value = 0;
-#ifdef UI_OUT
       ui_out_text (uiout, "Value returned has type: ");
       ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
       ui_out_text (uiout, ".");
       ui_out_text (uiout, " Cannot determine contents\n");
-#else /* UI_OUT */
-      printf_filtered ("Value returned has type: %s.", TYPE_NAME (value_type));
-      printf_filtered (" Cannot determine contents\n");
-#endif /* UI_OUT */
 #else
       value = value_being_returned (value_type, stop_registers, structure_return);
-#ifdef UI_OUT
       stb = ui_out_stream_new (uiout);
       ui_out_text (uiout, "Value returned is ");
       ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value));
@@ -1071,11 +1172,6 @@ print_return_value (int structure_return, struct type *value_type)
       value_print (value, stb->stream, 0, Val_no_prettyprint);
       ui_out_field_stream (uiout, "return-value", stb);
       ui_out_text (uiout, "\n");
-#else
-      printf_filtered ("Value returned is $%d = ", record_latest_value (value));
-      value_print (value, gdb_stdout, 0, Val_no_prettyprint);
-      printf_filtered ("\n");
-#endif
 #endif
     }
 }
@@ -1193,7 +1289,8 @@ finish_command (char *arg, int from_tty)
   if (from_tty)
     {
       printf_filtered ("Run till exit from ");
-      print_stack_frame (selected_frame, selected_frame_level, 0);
+      print_stack_frame (selected_frame,
+                        frame_relative_level (selected_frame), 0);
     }
 
   /* If running asynchronously and the target support asynchronous
@@ -1494,7 +1591,7 @@ do_registers_info (int regnum, int fpregs)
       print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
 
       /* Get the data in raw format.  */
-      if (read_relative_register_raw_bytes (i, raw_buffer))
+      if (! frame_register_read (selected_frame, i, raw_buffer))
        {
          printf_filtered ("*value not available*\n");
          continue;
@@ -1517,35 +1614,18 @@ do_registers_info (int regnum, int fpregs)
        {
          register int j;
 
-#ifdef INVALID_FLOAT
-         if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
-           printf_filtered ("<invalid float>");
-         else
-#endif
-           val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
-                      gdb_stdout, 0, 1, 0, Val_pretty_default);
+         val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+                    gdb_stdout, 0, 1, 0, Val_pretty_default);
 
          printf_filtered ("\t(raw 0x");
          for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
            {
-             register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
+             register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
              : REGISTER_RAW_SIZE (i) - 1 - j;
              printf_filtered ("%02x", (unsigned char) raw_buffer[idx]);
            }
          printf_filtered (")");
        }
-
-/* FIXME!  val_print probably can handle all of these cases now...  */
-
-      /* Else if virtual format is too long for printf,
-         print in hex a byte at a time.  */
-      else if (REGISTER_VIRTUAL_SIZE (i) > (int) sizeof (long))
-       {
-         register int j;
-         printf_filtered ("0x");
-         for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
-           printf_filtered ("%02x", (unsigned char) virtual_buffer[j]);
-       }
       /* Else print as integer in hex and in decimal.  */
       else
        {
@@ -1601,7 +1681,7 @@ registers_info (char *addr_exp, int fpregs)
       if (*addr_exp >= '0' && *addr_exp <= '9')
        regnum = atoi (addr_exp);       /* Take a number */
       if (regnum >= numregs)   /* Bad name, or bad number */
-       error ("%.*s: invalid register", end - addr_exp, addr_exp);
+       error ("%.*s: invalid register", (int) (end - addr_exp), addr_exp);
 
     found:
       DO_REGISTERS_INFO (regnum, fpregs);
@@ -1645,10 +1725,6 @@ nofp_registers_info (char *addr_exp, int from_tty)
 void
 attach_command (char *args, int from_tty)
 {
-#ifdef SOLIB_ADD
-  extern int auto_solib_add;
-#endif
-
   char *exec_file;
   char *full_exec_path = NULL;
 
@@ -1710,12 +1786,9 @@ attach_command (char *args, int from_tty)
     }
 
 #ifdef SOLIB_ADD
-  if (auto_solib_add)
-    {
-      /* Add shared library symbols from the newly attached process, if any.  */
-      SOLIB_ADD ((char *) 0, from_tty, &current_target);
-      re_enable_breakpoints_in_shlibs ();
-    }
+  /* Add shared library symbols from the newly attached process, if any.  */
+  SOLIB_ADD ((char *) 0, from_tty, &current_target, auto_solib_add);
+  re_enable_breakpoints_in_shlibs ();
 #endif
 
   /* Take any necessary post-attaching actions for this platform.
@@ -1753,13 +1826,13 @@ detach_command (char *args, int from_tty)
 
 /* Stop the execution of the target while running in async mode, in
    the backgound. */
-#ifdef UI_OUT
+
 void
 interrupt_target_command_wrapper (char *args, int from_tty)
 {
   interrupt_target_command (args, from_tty);
 }
-#endif
+
 static void
 interrupt_target_command (char *args, int from_tty)
 {
@@ -1774,11 +1847,7 @@ interrupt_target_command (char *args, int from_tty)
 static void
 float_info (char *addr_exp, int from_tty)
 {
-#ifdef FLOAT_INFO
-  FLOAT_INFO;
-#else
-  printf_filtered ("No floating point info available for this processor.\n");
-#endif
+  gdbarch_print_float_info (current_gdbarch, gdb_stdout, selected_frame);
 }
 \f
 /* ARGSUSED */
@@ -1797,15 +1866,17 @@ _initialize_infcmd (void)
 
   c = add_com ("tty", class_run, tty_command,
               "Set terminal for future runs of program being debugged.");
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
 
   c = add_set_cmd ("args", class_run, var_string_noescape,
                   (char *) &inferior_args,
                   "Set argument list to give program being debugged when it is started.\n\
 Follow this command with any number of args, to be passed to the program.",
                   &setlist);
-  add_show_from_set (c, &showlist);
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
+  set_cmd_sfunc (c, notice_args_set);
+  c = add_show_from_set (c, &showlist);
+  set_cmd_sfunc (c, notice_args_read);
 
   c = add_cmd
     ("environment", no_class, environment_info,
@@ -1813,17 +1884,17 @@ Follow this command with any number of args, to be passed to the program.",
 With an argument VAR, prints the value of environment variable VAR to\n\
 give the program being debugged.  With no arguments, prints the entire\n\
 environment to be given to the program.", &showlist);
-  c->completer = noop_completer;
+  set_cmd_completer (c, noop_completer);
 
   add_prefix_cmd ("unset", no_class, unset_command,
-                 "Complement to certain \"set\" commands",
+                 "Complement to certain \"set\" commands.",
                  &unsetlist, "unset ", 0, &cmdlist);
 
   c = add_cmd ("environment", class_run, unset_environment_command,
               "Cancel environment variable VAR for the program.\n\
 This does not affect the program until the next \"run\" command.",
               &unsetlist);
-  c->completer = noop_completer;
+  set_cmd_completer (c, noop_completer);
 
   c = add_cmd ("environment", class_run, set_environment_command,
               "Set environment variable value to give the program.\n\
@@ -1831,7 +1902,7 @@ Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
 VALUES of environment variables are uninterpreted strings.\n\
 This does not affect the program until the next \"run\" command.",
               &setlist);
-  c->completer = noop_completer;
+  set_cmd_completer (c, noop_completer);
 
   c = add_com ("path", class_files, path_command,
               "Add directory DIR(s) to beginning of search path for object files.\n\
@@ -1839,7 +1910,7 @@ $cwd in the path means the current working directory.\n\
 This path is equivalent to the $PATH shell variable.  It is a list of\n\
 directories, separated by colons.  These directories are searched to find\n\
 fully linked executable files and separately compiled object files as needed.");
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
 
   c = add_cmd ("paths", no_class, path_info,
               "Current search path for finding object files.\n\
@@ -1848,7 +1919,7 @@ This path is equivalent to the $PATH shell variable.  It is a list of\n\
 directories, separated by colons.  These directories are searched to find\n\
 fully linked executable files and separately compiled object files as needed.",
               &showlist);
-  c->completer = noop_completer;
+  set_cmd_completer (c, noop_completer);
 
   add_com ("attach", class_run, attach_command,
           "Attach to a process or file outside of GDB.\n\
@@ -1904,14 +1975,14 @@ Argument N means do this N times (or till program stops for another reason).");
               "Execute until the program reaches a source line greater than the current\n\
 or a specified line or address or function (same args as break command).\n\
 Execution will also stop upon exit from the current stack frame.");
-  c->completer = location_completer;
+  set_cmd_completer (c, location_completer);
   add_com_alias ("u", "until", class_run, 1);
 
   c = add_com ("jump", class_run, jump_command,
               "Continue program being debugged at specified line or address.\n\
 Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
 for an address to start at.");
-  c->completer = location_completer;
+  set_cmd_completer (c, location_completer);
 
   if (xdb_commands)
     {
@@ -1922,7 +1993,7 @@ address.\n\
 Give as argument either LINENUM or *ADDR, where ADDR is an \n\
 expression for an address to start at.\n\
 This command is a combination of tbreak and jump.");
-      c->completer = location_completer;
+      set_cmd_completer (c, location_completer);
     }
 
   if (xdb_commands)
@@ -1943,7 +2014,7 @@ Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
 With no arguments, uses arguments last specified (with \"run\" or \"set args\").\n\
 To cancel previous arguments and run with no arguments,\n\
 use \"set args\" without arguments.");
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
   add_com_alias ("r", "run", class_run, 1);
   if (xdb_commands)
     add_com ("R", class_run, run_no_args_command,
@@ -1971,7 +2042,6 @@ Register name as argument means describe only that register.");
   add_info ("float", float_info,
            "Print the status of the floating point unit\n");
 
-  set_inferior_args (xstrdup (""));    /* Initially no args */
   inferior_environ = make_environ ();
   init_environ (inferior_environ);
 }
This page took 0.031647 seconds and 4 git commands to generate.