/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbsupport/version.h"
#include "serial.h"
#include "main.h"
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
#include "gdbthread.h"
#include "extension.h"
#include "interps.h"
#include "filenames.h"
#include "frame.h"
#include "gdbsupport/buffer.h"
-#include "gdb_select.h"
+#include "gdbsupport/gdb_select.h"
#include "gdbsupport/scope-exit.h"
#include "gdbarch.h"
#include "gdbsupport/pathstuff.h"
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
command. We need this as when a command is running, saved_command_line
already contains the line of the currently executing command. */
-char *previous_saved_command_line;
+static char *previous_saved_command_line;
/* If not NULL, the arguments that should be passed if the
previous_saved_command_line is repeated. */
whatever) can issue its own commands and also send along commands
from the user, and have the user not notice that the user interface
is issuing commands too. */
-int server_command;
+bool server_command;
/* Timeout limit for response from target. */
int remote_timeout = 2;
-/* Non-zero tells remote* modules to output debugging info. */
-
-int remote_debug = 0;
-
/* Sbrk location on entry to main. Used for statistics only. */
#ifdef HAVE_USEFUL_SBRK
char *lim_at_start;
command_handler (command);
}
}
-\f
-void (*pre_init_ui_hook) (void);
#ifdef __MSDOS__
static void
{
if (language_mode == language_mode_auto && info_verbose)
{
- language_info (1); /* Print what changed. */
+ /* Print what changed. */
+ language_info ();
}
warned = 0;
}
scoped_restore save_ui = make_scoped_restore (¤t_ui);
struct ui *ui = current_ui;
+ /* We're about to wait until the target stops after having resumed
+ it so must force-commit resumptions, in case we're being called
+ in some context where a scoped_disable_commit_resumed object is
+ active. I.e., this function is a commit-resumed sync/flush
+ point. */
+ scoped_enable_commit_resumed enable ("sync wait");
+
while (gdb_do_one_event () >= 0)
if (ui->prompt_state != PROMPT_BLOCKED)
break;
{
const char *cmd = p;
const char *arg;
+ std::string default_args;
+ std::string default_args_and_arg;
int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
line = p;
/* If trace-commands is set then this will print this command. */
print_command_trace ("%s", p);
- c = lookup_cmd (&cmd, cmdlist, "", 0, 1);
+ c = lookup_cmd (&cmd, cmdlist, "", &default_args, 0, 1);
p = cmd;
scoped_restore save_repeat_args
= make_scoped_restore (&repeat_arguments, nullptr);
const char *args_pointer = p;
- /* Pass null arg rather than an empty one. */
- arg = *p ? p : 0;
+ if (!default_args.empty ())
+ {
+ if (*p != '\0')
+ default_args_and_arg = default_args + ' ' + p;
+ else
+ default_args_and_arg = default_args;
+ arg = default_args_and_arg.c_str ();
+ }
+ else
+ {
+ /* Pass null arg rather than an empty one. */
+ arg = *p == '\0' ? nullptr : p;
+ }
/* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
- while the is_complete_command(cfunc) test is just plain
- bogus. They should both be replaced by a test of the form
- c->strip_trailing_white_space_p. */
+ while the is_complete_command(cfunc) test is just plain
+ bogus. They should both be replaced by a test of the form
+ c->strip_trailing_white_space_p. */
/* NOTE: cagney/2002-02-02: The function.cfunc in the below
- can't be replaced with func. This is because it is the
- cfunc, and not the func, that has the value that the
- is_complete_command hack is testing for. */
+ can't be replaced with func. This is because it is the
+ cfunc, and not the func, that has the value that the
+ is_complete_command hack is testing for. */
/* Clear off trailing whitespace, except for set and complete
- command. */
+ command. */
std::string without_whitespace;
if (arg
&& c->type != set_cmd
execute_cmd_pre_hook (c);
if (c->deprecated_warn_user)
- deprecated_cmd_warning (line);
+ deprecated_cmd_warning (line, cmdlist);
/* c->user_commands would be NULL in the case of a python command. */
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. */
{
+ std::string prefixname = c->prefixname ();
+ std::string prefixname_no_space
+ = prefixname.substr (0, prefixname.length () - 1);
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);
+ ("\"%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);
}
}
-/* Run execute_command for P and FROM_TTY. Capture its output into the
- returned string, do not display it to the screen. BATCH_FLAG will be
- temporarily set to true. */
+/* See gdbcmd.h. */
std::string
execute_command_to_string (const char *p, int from_tty,
if (prompt != NULL)
{
/* Don't use a _filtered function here. It causes the assumed
- character position to be off, since the newline we read from
- the user is not accounted for. */
+ character position to be off, since the newline we read from
+ the user is not accounted for. */
fputs_unfiltered (prompt, gdb_stdout);
gdb_flush (gdb_stdout);
}
/* static */ bool history_expansion_p;
+/* Should we write out the command history on exit? In order to write out
+ the history both this flag must be true, and the history_filename
+ variable must be set to something sensible. */
static bool write_history_p;
+
+/* 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)
{
- fprintf_filtered (file, _("Saving of the history record on exit is %s.\n"),
- value);
+ if (!write_history_p || !history_filename_empty ())
+ fprintf_filtered (file, _("Saving of the history record on exit is %s.\n"),
+ value);
+ else
+ fprintf_filtered (file, _("Saving of the history is disabled due to "
+ "the value of 'history filename'.\n"));
}
/* The variable associated with the "set/show history size"
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)
{
- fprintf_filtered (file, _("The filename in which to record "
- "the command history is \"%ps\".\n"),
- styled_string (file_name_style.style (), value));
+ 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));
+ else
+ fprintf_filtered (file, _("There is no filename currently set for "
+ "recording the command history in.\n"));
}
/* This is like readline(), but it has some gdb-specific behavior.
ret = rename (local_history_filename.c_str (), history_filename);
saved_errno = errno;
if (ret < 0 && saved_errno != EEXIST)
- warning (_("Could not rename %s to %s: %s"),
+ warning (_("Could not rename %s to %s: %s"),
local_history_filename.c_str (), history_filename,
safe_strerror (saved_errno));
}
gdb::unique_xmalloc_ptr<char> rl;
/* Make sure that all output has been output. Some machines may
- let you get away with leaving out some of the gdb_flush, but
- not all. */
+ let you get away with leaving out some of the gdb_flush, but
+ not all. */
wrap_here ("");
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
program to parse, and is just canonical program name and version
number, which starts after last space. */
- ui_file_style style;
- if (interactive)
- {
- ui_file_style nstyle = { ui_file_style::MAGENTA, ui_file_style::NONE,
- ui_file_style::BOLD };
- style = nstyle;
- }
- fprintf_styled (stream, style, "GNU gdb %s%s\n", PKGVERSION, version);
+ std::string v_str = string_printf ("GNU gdb %s%s", PKGVERSION, version);
+ fprintf_filtered (stream, "%ps\n",
+ styled_string (version_style.style (), v_str.c_str ()));
/* Second line is a copyright notice. */
fprintf_filtered (stream,
- "Copyright (C) 2020 Free Software Foundation, Inc.\n");
+ "Copyright (C) 2021 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
"), host_name, target_name);
fprintf_filtered (stream, _("\
- --with-auto-load-dir=%s\n\
- --with-auto-load-safe-path=%s\n\
+ --with-auto-load-dir=%s\n\
+ --with-auto-load-safe-path=%s\n\
"), AUTO_LOAD_DIR, AUTO_LOAD_SAFE_PATH);
#if HAVE_LIBEXPAT
fprintf_filtered (stream, _("\
- --with-expat\n\
+ --with-expat\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-expat\n\
+ --without-expat\n\
"));
#endif
if (GDB_DATADIR[0])
fprintf_filtered (stream, _("\
- --with-gdb-datadir=%s%s\n\
+ --with-gdb-datadir=%s%s\n\
"), GDB_DATADIR, GDB_DATADIR_RELOCATABLE ? " (relocatable)" : "");
#ifdef ICONV_BIN
fprintf_filtered (stream, _("\
- --with-iconv-bin=%s%s\n\
+ --with-iconv-bin=%s%s\n\
"), ICONV_BIN, ICONV_BIN_RELOCATABLE ? " (relocatable)" : "");
#endif
if (JIT_READER_DIR[0])
fprintf_filtered (stream, _("\
- --with-jit-reader-dir=%s%s\n\
+ --with-jit-reader-dir=%s%s\n\
"), JIT_READER_DIR, JIT_READER_DIR_RELOCATABLE ? " (relocatable)" : "");
#if HAVE_LIBUNWIND_IA64_H
fprintf_filtered (stream, _("\
- --with-libunwind-ia64\n\
+ --with-libunwind-ia64\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-libunwind-ia64\n\
+ --without-libunwind-ia64\n\
"));
#endif
#if HAVE_LIBLZMA
fprintf_filtered (stream, _("\
- --with-lzma\n\
+ --with-lzma\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-lzma\n\
+ --without-lzma\n\
"));
#endif
#if HAVE_LIBBABELTRACE
fprintf_filtered (stream, _("\
- --with-babeltrace\n\
+ --with-babeltrace\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-babeltrace\n\
+ --without-babeltrace\n\
"));
#endif
#if HAVE_LIBIPT
fprintf_filtered (stream, _("\
- --with-intel-pt\n\
+ --with-intel-pt\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-intel-pt\n\
+ --without-intel-pt\n\
"));
#endif
#if HAVE_LIBMPFR
fprintf_filtered (stream, _("\
- --with-mpfr\n\
+ --with-mpfr\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-mpfr\n\
+ --without-mpfr\n\
"));
#endif
#if HAVE_LIBXXHASH
fprintf_filtered (stream, _("\
- --with-xxhash\n\
+ --with-xxhash\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-xxhash\n\
+ --without-xxhash\n\
"));
#endif
#ifdef WITH_PYTHON_PATH
fprintf_filtered (stream, _("\
- --with-python=%s%s\n\
+ --with-python=%s%s\n\
"), WITH_PYTHON_PATH, PYTHON_PATH_RELOCATABLE ? " (relocatable)" : "");
#else
fprintf_filtered (stream, _("\
- --without-python\n\
+ --without-python\n\
+"));
+#endif
+#ifdef WITH_PYTHON_LIBDIR
+ fprintf_filtered (stream, _("\
+ --with-python-libdir=%s%s\n\
+"), WITH_PYTHON_LIBDIR, PYTHON_LIBDIR_RELOCATABLE ? " (relocatable)" : "");
+#else
+ fprintf_filtered (stream, _("\
+ --without-python-libdir\n\
+"));
+#endif
+
+#if HAVE_LIBDEBUGINFOD
+ fprintf_filtered (stream, _("\
+ --with-debuginfod\n\
+"));
+#else
+ fprintf_filtered (stream, _("\
+ --without-debuginfod\n\
"));
#endif
#if HAVE_GUILE
fprintf_filtered (stream, _("\
- --with-guile\n\
+ --with-guile\n\
"));
#else
fprintf_filtered (stream, _("\
- --without-guile\n\
+ --without-guile\n\
"));
#endif
#if HAVE_SOURCE_HIGHLIGHT
fprintf_filtered (stream, _("\
- --enable-source-highlight\n\
+ --enable-source-highlight\n\
"));
#else
fprintf_filtered (stream, _("\
- --disable-source-highlight\n\
+ --disable-source-highlight\n\
"));
#endif
#ifdef RELOC_SRCDIR
fprintf_filtered (stream, _("\
- --with-relocated-sources=%s\n\
+ --with-relocated-sources=%s\n\
"), RELOC_SRCDIR);
#endif
if (DEBUGDIR[0])
fprintf_filtered (stream, _("\
- --with-separate-debug-dir=%s%s\n\
+ --with-separate-debug-dir=%s%s\n\
"), DEBUGDIR, DEBUGDIR_RELOCATABLE ? " (relocatable)" : "");
if (TARGET_SYSTEM_ROOT[0])
fprintf_filtered (stream, _("\
- --with-sysroot=%s%s\n\
+ --with-sysroot=%s%s\n\
"), TARGET_SYSTEM_ROOT, TARGET_SYSTEM_ROOT_RELOCATABLE ? " (relocatable)" : "");
if (SYSTEM_GDBINIT[0])
fprintf_filtered (stream, _("\
- --with-system-gdbinit=%s%s\n\
+ --with-system-gdbinit=%s%s\n\
"), SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE ? " (relocatable)" : "");
if (SYSTEM_GDBINIT_DIR[0])
fprintf_filtered (stream, _("\
- --with-system-gdbinit-dir=%s%s\n\
+ --with-system-gdbinit-dir=%s%s\n\
"), SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE ? " (relocatable)" : "");
/* We assume "relocatable" will be printed at least once, thus we always
switch_to_thread (thread);
/* Leave core files alone. */
- if (target_has_execution)
+ if (target_has_execution ())
{
if (inf->attach_flag)
target_detach (inf, from_tty);
{
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)
+ for (ui *ui : all_uis ())
{
if (input_interactive_p (ui))
{
static void
show_interactive_mode (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
+ 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, input_interactive_p (current_ui) ? "on" : "off");
+ "is %s (currently %s).\n",
+ value, input_interactive_p (current_ui) ? "on" : "off");
else
fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
}
set_readline_history_size (history_size_setshow_var);
}
-void
-set_history (const char *args, int from_tty)
-{
- printf_unfiltered (_("\"set history\" must be followed "
- "by the name of a history subcommand.\n"));
- help_list (sethistlist, "set history ", all_commands, gdb_stdout);
-}
-
-void
-show_history (const char *args, int from_tty)
-{
- cmd_show_list (showhistlist, from_tty, "");
-}
-
bool info_verbose = false; /* Default verbose msgs off. */
/* Called by do_set_command. An elaborate joke. */
const char *cmdname = "verbose";
struct cmd_list_element *showcmd;
- showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1);
+ showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, NULL, 1);
gdb_assert (showcmd != NULL && showcmd != CMD_LIST_AMBIGUOUS);
if (c->doc && c->doc_allocated)
set_readline_history_size (history_size_setshow_var);
tmpenv = getenv ("GDBHISTFILE");
- if (tmpenv)
+ if (tmpenv != nullptr)
history_filename = xstrdup (tmpenv);
- else if (!history_filename)
+ 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. */
+ 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";
gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
history_filename = temp.release ();
}
- read_history (history_filename);
+
+ if (!history_filename_empty ())
+ read_history (history_filename);
}
static void
value);
}
-/* New values of the "data-directory" parameter are staged here. */
+/* New values of the "data-directory" parameter are staged here.
+ 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;
/* "set" command for the gdb_datadir configuration variable. */
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 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 ());
+
gdb::observers::gdb_datadir_changed.notify ();
}
gdb_datadir.c_str ()));
}
+/* Implement 'set history filename'. */
+
static void
set_history_filename (const char *args,
int from_tty, struct cmd_list_element *c)
/* 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 (!IS_ABSOLUTE_PATH (history_filename))
+ if (!history_filename_empty () && !IS_ABSOLUTE_PATH (history_filename))
{
gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (history_filename));
}
}
+/* 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)
{
show_history_remove_duplicates,
&sethistlist, &showhistlist);
- add_setshow_filename_cmd ("filename", no_class, &history_filename, _("\
+ add_setshow_optional_filename_cmd ("filename", no_class, &history_filename, _("\
Set the filename in which to record the command history."), _("\
Show the filename in which to record the command history."), _("\
(the list of previous commands of which a record is kept)."),
&setlist, &showlist);
add_setshow_filename_cmd ("data-directory", class_maintenance,
- &staged_gdb_datadir, _("Set GDB's data directory."),
- _("Show GDB's data directory."),
- _("\
+ &staged_gdb_datadir, _("Set GDB's data directory."),
+ _("Show GDB's data directory."),
+ _("\
When set, GDB uses the specified path to search for data files."),
- set_gdb_datadir, show_gdb_datadir,
- &setlist,
- &showlist);
+ set_gdb_datadir, show_gdb_datadir,
+ &setlist,
+ &showlist);
+ /* Prime the initial value for data-directory. */
+ staged_gdb_datadir = strdup (gdb_datadir.c_str ());
add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
- &interactive_mode, _("\
+ &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\
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);
+ NULL,
+ 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\
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 ("");
- if (pre_init_ui_hook)
- pre_init_ui_hook ();
-
/* Run the init function of each source file. */
#ifdef __MSDOS__
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 ();
}