Fix the remote-sim.c build
[binutils-gdb.git] / gdb / top.c
index c374a8d02d383db4db891ca1822a7ff38f77a4c5..07695f88fd449f263a241def454196c43e75293a 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1,6 +1,6 @@
 /* Top level stuff for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -84,8 +84,6 @@
 
 extern void initialize_all_files (void);
 
-static bool history_filename_empty (void);
-
 #define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt
 #define PREFIX(X) the_prompts.prompt_stack[the_prompts.top + X].prefix
 #define SUFFIX(X) the_prompts.prompt_stack[the_prompts.top + X].suffix
@@ -335,13 +333,11 @@ ui::~ui ()
 static gdb_file_up
 open_terminal_stream (const char *name)
 {
-  int fd;
-
-  fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
-  if (fd < 0)
+  scoped_fd fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
+  if (fd.get () < 0)
     perror_with_name  (_("opening terminal failed"));
 
-  return gdb_file_up (fdopen (fd, "w+"));
+  return fd.to_file ("w+");
 }
 
 /* Implementation of the "new-ui" command.  */
@@ -389,7 +385,7 @@ new_ui_command (const char *args, int from_tty)
     ui.release ();
   }
 
-  printf_unfiltered ("New UI allocated\n");
+  printf_filtered ("New UI allocated\n");
 }
 
 /* Handler for SIGHUP.  */
@@ -647,22 +643,26 @@ execute_command (const char *p, int from_tty)
       if (c->theclass == class_user && c->user_commands)
        execute_user_command (c, arg);
       else if (c->theclass == class_user
-              && c->prefixlist && !c->allow_unknown)
+              && c->is_prefix () && !c->allow_unknown)
        /* If this is a user defined prefix that does not allow unknown
           (in other words, C is a prefix command and not a command
           that can be followed by its args), report the list of
           subcommands.  */
        {
-         printf_unfiltered
-           ("\"%.*s\" must be followed by the name of a subcommand.\n",
-            (int) strlen (c->prefixname) - 1, c->prefixname);
-         help_list (*c->prefixlist, c->prefixname, all_commands, gdb_stdout);
+         std::string prefixname = c->prefixname ();
+          std::string prefixname_no_space
+           = prefixname.substr (0, prefixname.length () - 1);
+         printf_filtered
+           ("\"%s\" must be followed by the name of a subcommand.\n",
+            prefixname_no_space.c_str ());
+         help_list (*c->subcommands, prefixname.c_str (), all_commands,
+                    gdb_stdout);
        }
       else if (c->type == set_cmd)
        do_set_command (arg, from_tty, c);
       else if (c->type == show_cmd)
        do_show_command (arg, from_tty, c);
-      else if (!cmd_func_p (c))
+      else if (c->is_command_class_help ())
        error (_("That is not a command, just a help topic."));
       else if (deprecated_call_command_hook)
        deprecated_call_command_hook (c, arg, from_tty);
@@ -692,12 +692,10 @@ execute_command (const char *p, int from_tty)
   cleanup_if_error.release ();
 }
 
-/* Run execute_command for P and FROM_TTY.  Sends its output to FILE,
-   do not display it to the screen.  BATCH_FLAG will be
-   temporarily set to true.  */
+/* See gdbcmd.h.  */
 
 void
-execute_command_to_ui_file (struct ui_file *file, const char *p, int from_tty)
+execute_fn_to_ui_file (struct ui_file *file, std::function<void(void)> fn)
 {
   /* GDB_STDOUT should be better already restored during these
      restoration callbacks.  */
@@ -720,22 +718,62 @@ execute_command_to_ui_file (struct ui_file *file, const char *p, int from_tty)
     scoped_restore save_stdtargerr
       = make_scoped_restore (&gdb_stdtargerr, file);
 
-    execute_command (p, from_tty);
+    fn ();
   }
 }
 
 /* See gdbcmd.h.  */
 
-std::string
-execute_command_to_string (const char *p, int from_tty,
-                          bool term_out)
+void
+execute_fn_to_string (std::string &res, std::function<void(void)> fn,
+                     bool term_out)
 {
   string_file str_file (term_out);
 
-  execute_command_to_ui_file (&str_file, p, from_tty);
-  return std::move (str_file.string ());
+  try
+    {
+      execute_fn_to_ui_file (&str_file, fn);
+    }
+  catch (...)
+    {
+      /* Finally.  */
+      res = std::move (str_file.string ());
+      throw;
+    }
+
+  /* And finally.  */
+  res = std::move (str_file.string ());
+}
+
+/* See gdbcmd.h.  */
+
+void
+execute_command_to_ui_file (struct ui_file *file,
+                           const char *p, int from_tty)
+{
+  execute_fn_to_ui_file (file, [=]() { execute_command (p, from_tty); });
 }
 
+/* See gdbcmd.h.  */
+
+void
+execute_command_to_string (std::string &res, const char *p, int from_tty,
+                          bool term_out)
+{
+  execute_fn_to_string (res, [=]() { execute_command (p, from_tty); },
+                       term_out);
+}
+
+/* See gdbcmd.h.  */
+
+void
+execute_command_to_string (const char *p, int from_tty,
+                          bool term_out)
+{
+  std::string dummy;
+  execute_fn_to_string (dummy, [=]() { execute_command (p, from_tty); },
+                       term_out);
+}
 \f
 /* When nonzero, cause dont_repeat to do nothing.  This should only be
    set via prevent_dont_repeat.  */
@@ -904,12 +942,16 @@ static bool command_editing_p;
    variable must be set to something sensible.  */
 static bool write_history_p;
 
+/* The name of the file in which GDB history will be written.  If this is
+   set to NULL, of the empty string then history will not be written.  */
+static std::string history_filename;
+
 /* Implement 'show history save'.  */
 static void
 show_write_history_p (struct ui_file *file, int from_tty,
                      struct cmd_list_element *c, const char *value)
 {
-  if (!write_history_p || !history_filename_empty ())
+  if (!write_history_p || !history_filename.empty ())
     fprintf_filtered (file, _("Saving of the history record on exit is %s.\n"),
                      value);
   else
@@ -943,24 +985,12 @@ show_history_remove_duplicates (struct ui_file *file, int from_tty,
                    value);
 }
 
-/* The name of the file in which GDB history will be written.  If this is
-   set to NULL, of the empty string then history will not be written.  */
-static char *history_filename;
-
-/* Return true if the history_filename is either NULL or the empty string,
-   indicating that we should not try to read, nor write out the history.  */
-static bool
-history_filename_empty (void)
-{
-  return (history_filename == nullptr || *history_filename == '\0');
-}
-
 /* Implement 'show history filename'.  */
 static void
 show_history_filename (struct ui_file *file, int from_tty,
                       struct cmd_list_element *c, const char *value)
 {
-  if (!history_filename_empty ())
+  if (!history_filename.empty ())
     fprintf_filtered (file, _("The filename in which to record "
                              "the command history is \"%ps\".\n"),
                      styled_string (file_name_style.style (), value));
@@ -1227,14 +1257,15 @@ gdb_safe_append_history (void)
   int ret, saved_errno;
 
   std::string local_history_filename
-    = string_printf ("%s-gdb%ld~", history_filename, (long) getpid ());
+    = string_printf ("%s-gdb%ld~", history_filename.c_str (), (long) getpid ());
 
-  ret = rename (history_filename, local_history_filename.c_str ());
+  ret = rename (history_filename.c_str (), local_history_filename.c_str ());
   saved_errno = errno;
   if (ret < 0 && saved_errno != ENOENT)
     {
       warning (_("Could not rename %ps to %ps: %s"),
-              styled_string (file_name_style.style (), history_filename),
+              styled_string (file_name_style.style (),
+                             history_filename.c_str ()),
               styled_string (file_name_style.style (),
                              local_history_filename.c_str ()),
               safe_strerror (saved_errno));
@@ -1262,11 +1293,11 @@ gdb_safe_append_history (void)
                                   history_max_entries);
        }
 
-      ret = rename (local_history_filename.c_str (), history_filename);
+      ret = rename (local_history_filename.c_str (), history_filename.c_str ());
       saved_errno = errno;
       if (ret < 0 && saved_errno != EEXIST)
        warning (_("Could not rename %s to %s: %s"),
-                local_history_filename.c_str (), history_filename,
+                local_history_filename.c_str (), history_filename.c_str (),
                 safe_strerror (saved_errno));
     }
 }
@@ -1404,7 +1435,7 @@ print_gdb_version (struct ui_file *stream, bool interactive)
   /* Second line is a copyright notice.  */
 
   fprintf_filtered (stream,
-                   "Copyright (C) 2021 Free Software Foundation, Inc.\n");
+                   "Copyright (C) 2022 Free Software Foundation, Inc.\n");
 
   /* Following the copyright is a brief statement that the program is
      free software, that users are free to copy and change it on
@@ -1639,12 +1670,12 @@ tree, and GDB will still find it.)\n\
 
 /* The current top level prompt, settable with "set prompt", and/or
    with the python `gdb.prompt_hook' hook.  */
-static char *top_prompt;
+static std::string top_prompt;
 
 /* Access method for the GDB prompt string.  */
 
-char *
-get_prompt (void)
+const std::string &
+get_prompt ()
 {
   return top_prompt;
 }
@@ -1654,10 +1685,7 @@ get_prompt (void)
 void
 set_prompt (const char *s)
 {
-  char *p = xstrdup (s);
-
-  xfree (top_prompt);
-  top_prompt = p;
+  top_prompt = s;
 }
 \f
 
@@ -1756,8 +1784,6 @@ quit_force (int *exit_arg, int from_tty)
 {
   int exit_code = 0;
 
-  undo_terminal_modifications_before_exit ();
-
   /* An optional expression may be used to cause gdb to terminate with the
      value of that expression.  */
   if (exit_arg)
@@ -1765,6 +1791,10 @@ quit_force (int *exit_arg, int from_tty)
   else if (return_child_result)
     exit_code = return_child_result_value;
 
+  gdb::observers::gdb_exiting.notify (exit_code);
+
+  undo_terminal_modifications_before_exit ();
+
   /* We want to handle any quit errors and exit regardless.  */
 
   /* Get out of tfind mode, and kill or detach all inferiors.  */
@@ -1797,7 +1827,7 @@ quit_force (int *exit_arg, int from_tty)
   /* Save the history information if it is appropriate to do so.  */
   try
     {
-      if (write_history_p && history_filename)
+      if (write_history_p && !history_filename.empty ())
        {
          int save = 0;
 
@@ -2045,27 +2075,8 @@ init_history (void)
 
   set_readline_history_size (history_size_setshow_var);
 
-  tmpenv = getenv ("GDBHISTFILE");
-  if (tmpenv != nullptr)
-    history_filename = xstrdup (tmpenv);
-  else if (history_filename == nullptr)
-    {
-      /* We include the current directory so that if the user changes
-        directories the file written will be the same as the one
-        that was read.  */
-#ifdef __MSDOS__
-      /* No leading dots in file names are allowed on MSDOS.  */
-      const char *fname = "_gdb_history";
-#else
-      const char *fname = ".gdb_history";
-#endif
-
-      gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
-      history_filename = temp.release ();
-    }
-
-  if (!history_filename_empty ())
-    read_history (history_filename);
+  if (!history_filename.empty ())
+    read_history (history_filename.c_str ());
 }
 
 static void
@@ -2115,21 +2126,20 @@ show_exec_done_display_p (struct ui_file *file, int from_tty,
    Extension languages, for example Python's gdb.parameter API, will read
    the value directory from this variable, so we must ensure that this
    always contains the correct value.  */
-static char *staged_gdb_datadir;
+static std::string staged_gdb_datadir;
 
 /* "set" command for the gdb_datadir configuration variable.  */
 
 static void
 set_gdb_datadir (const char *args, int from_tty, struct cmd_list_element *c)
 {
-  set_gdb_data_directory (staged_gdb_datadir);
+  set_gdb_data_directory (staged_gdb_datadir.c_str ());
 
   /* SET_GDB_DATA_DIRECTORY will resolve relative paths in
      STAGED_GDB_DATADIR, so we now copy the value from GDB_DATADIR
      back into STAGED_GDB_DATADIR so the extension languages can read the
      correct value.  */
-  free (staged_gdb_datadir);
-  staged_gdb_datadir = strdup (gdb_datadir.c_str ());
+  staged_gdb_datadir = gdb_datadir;
 
   gdb::observers::gdb_datadir_changed.notify ();
 }
@@ -2154,15 +2164,38 @@ set_history_filename (const char *args,
   /* We include the current directory so that if the user changes
      directories the file written will be the same as the one
      that was read.  */
-  if (!history_filename_empty () && !IS_ABSOLUTE_PATH (history_filename))
+  if (!history_filename.empty ()
+      && !IS_ABSOLUTE_PATH (history_filename.c_str ()))
     {
-      gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (history_filename));
+      gdb::unique_xmalloc_ptr<char> temp
+       (gdb_abspath (history_filename.c_str ()));
 
-      xfree (history_filename);
-      history_filename = temp.release ();
+      history_filename = temp.get ();
     }
 }
 
+/* Whether we're in quiet startup mode.  */
+
+static bool startup_quiet;
+
+/* See top.h.  */
+
+bool
+check_quiet_mode ()
+{
+  return startup_quiet;
+}
+
+/* Show whether GDB should start up in quiet mode.  */
+
+static void
+show_startup_quiet (struct ui_file *file, int from_tty,
+             struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Whether to start up quietly is %s.\n"),
+                   value);
+}
+
 static void
 init_gdb_version_vars (void)
 {
@@ -2303,7 +2336,7 @@ When set, GDB uses the specified path to search for data files."),
                           &setlist,
                            &showlist);
   /* Prime the initial value for data-directory.  */
-  staged_gdb_datadir = strdup (gdb_datadir.c_str ());
+  staged_gdb_datadir = gdb_datadir;
 
   add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
                                &interactive_mode, _("\
@@ -2319,6 +2352,17 @@ input settings."),
                        show_interactive_mode,
                        &setlist, &showlist);
 
+  add_setshow_boolean_cmd ("startup-quietly", class_support,
+                              &startup_quiet, _("\
+Set whether GDB should start up quietly."), _("                \
+Show whether GDB should start up quietly."), _("\
+This setting will not affect the current session.  Instead this command\n\
+should be added to the .gdbearlyinit file in the users home directory to\n\
+affect future GDB sessions."),
+                              NULL,
+                              show_startup_quiet,
+                              &setlist, &showlist);
+
   c = add_cmd ("new-ui", class_support, new_ui_command, _("\
 Create a new UI.\n\
 Usage: new-ui INTERPRETER TTY\n\
@@ -2327,8 +2371,10 @@ The second argument is the terminal the UI runs on."), &cmdlist);
   set_cmd_completer (c, interpreter_completer);
 }
 
+/* See top.h.  */
+
 void
-gdb_init (char *argv0)
+gdb_init ()
 {
   saved_command_line = xstrdup ("");
   previous_saved_command_line = xstrdup ("");
@@ -2364,7 +2410,7 @@ gdb_init (char *argv0)
      to alter it.  */
   set_initial_gdb_ttystate ();
 
-  async_init_signals ();
+  gdb_init_signals ();
 
   /* We need a default language for parsing expressions, so simple
      things like "set width 0" won't fail if no language is explicitly
@@ -2373,12 +2419,31 @@ gdb_init (char *argv0)
   set_language (language_c);
   expected_language = current_language;        /* Don't warn about the change.  */
 
-  /* Python initialization, for example, can require various commands to be
-     installed.  For example "info pretty-printer" needs the "info"
-     prefix to be installed.  Keep things simple and just do final
-     script initialization here.  */
-  finish_ext_lang_initialization ();
-
   /* Create $_gdb_major and $_gdb_minor convenience variables.  */
   init_gdb_version_vars ();
 }
+
+void _initialize_top ();
+void
+_initialize_top ()
+{
+  /* Determine a default value for the history filename.  */
+  const char *tmpenv = getenv ("GDBHISTFILE");
+  if (tmpenv != nullptr)
+    history_filename = tmpenv;
+  else
+    {
+      /* We include the current directory so that if the user changes
+        directories the file written will be the same as the one
+        that was read.  */
+#ifdef __MSDOS__
+      /* No leading dots in file names are allowed on MSDOS.  */
+      const char *fname = "_gdb_history";
+#else
+      const char *fname = ".gdb_history";
+#endif
+
+      gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
+      history_filename = temp.get ();
+    }
+}