/* 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.
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
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. */
ui.release ();
}
- printf_unfiltered ("New UI allocated\n");
+ printf_filtered ("New UI allocated\n");
}
/* Handler for SIGHUP. */
std::string prefixname = c->prefixname ();
std::string prefixname_no_space
= prefixname.substr (0, prefixname.length () - 1);
- printf_unfiltered
+ 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,
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. */
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. */
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
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));
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));
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));
}
}
/* 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
/* 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;
}
void
set_prompt (const char *s)
{
- char *p = xstrdup (s);
-
- xfree (top_prompt);
- top_prompt = p;
+ top_prompt = s;
}
\f
{
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)
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. */
/* 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;
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
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 ();
}
/* 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 ();
}
}
&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, _("\
show_interactive_mode,
&setlist, &showlist);
- c = add_setshow_boolean_cmd ("startup-quietly", class_support,
+ add_setshow_boolean_cmd ("startup-quietly", class_support,
&startup_quiet, _("\
Set whether GDB should start up quietly."), _(" \
Show whether GDB should start up quietly."), _("\
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
/* 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 ();
+ }
+}