/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2023 Free Software Foundation, Inc.
This file is part of GDB.
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
#include "ui-out.h"
#include "interps.h"
#include "event-top.h"
#include "infrun.h"
#include "gdbsupport/signals-state-save-restore.h"
+#include <algorithm>
#include <vector>
#include "gdbsupport/pathstuff.h"
#include "cli/cli-style.h"
+#ifdef GDBTK
+#include "gdbtk/generic/gdbtk.h"
+#endif
+#include "gdbsupport/alt-stack.h"
+#include "observable.h"
+#include "serial.h"
-/* The selected interpreter. This will be used as a set command
- variable, so it should always be malloc'ed - since
- do_setshow_command will free it. */
-char *interpreter_p;
-
-/* Whether dbx commands will be handled. */
-int dbx_commands = 0;
+/* The selected interpreter. */
+std::string interpreter_p;
/* System root path, used to find libraries etc. */
-char *gdb_sysroot = 0;
+std::string gdb_sysroot;
/* GDB datadir, used to store data files. */
std::string gdb_datadir;
{
int save_errno = errno;
- fprintf_unfiltered (gdb_stderr, "Warning: ");
+ gdb_printf (gdb_stderr, "Warning: ");
print_sys_errmsg (new_datadir, save_errno);
}
else if (!S_ISDIR (st.st_mode))
- warning (_("%s is not a directory."), new_datadir);
+ warning (_("%ps is not a directory."),
+ styled_string (file_name_style.style (), new_datadir));
gdb_datadir = gdb_realpath (new_datadir).get ();
"../foo" and "../foo" doesn't exist then we'll record $(pwd)/../foo which
isn't canonical, but that's ok. */
if (!IS_ABSOLUTE_PATH (gdb_datadir.c_str ()))
- {
- gdb::unique_xmalloc_ptr<char> abs_datadir
- = gdb_abspath (gdb_datadir.c_str ());
-
- gdb_datadir = abs_datadir.get ();
- }
+ gdb_datadir = gdb_abspath (gdb_datadir.c_str ());
}
/* Relocate a file or directory. PROGNAME is the name by which gdb
otherwise. */
static std::string
-relocate_gdbinit_path_maybe_in_datadir (const std::string& file)
+relocate_file_path_maybe_in_datadir (const std::string &file,
+ bool relocatable)
{
size_t datadir_len = strlen (GDB_DATADIR);
size_t start = datadir_len;
for (; IS_DIR_SEPARATOR (file[start]); ++start)
;
- relocated_path = (std::string (gdb_datadir) + SLASH_STRING
- + file.substr (start));
+ relocated_path = gdb_datadir + SLASH_STRING + file.substr (start);
}
else
{
- relocated_path = relocate_path (gdb_program_name,
- file.c_str (),
- SYSTEM_GDBINIT_RELOCATABLE);
+ relocated_path = relocate_path (gdb_program_name, file.c_str (),
+ relocatable);
}
return relocated_path;
}
-/* Compute the locations of init files that GDB should source and
- return them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If
- there is no system gdbinit (resp. home gdbinit and local gdbinit)
- to be loaded, then SYSTEM_GDBINIT (resp. HOME_GDBINIT and
- LOCAL_GDBINIT) is set to the empty string. */
-static void
-get_init_files (std::string *system_gdbinit,
- std::string *home_gdbinit,
- std::string *local_gdbinit)
-{
- static std::string sysgdbinit;
- static std::string homeinit;
- static std::string localinit;
- static int initialized = 0;
+/* A class to wrap up the logic for finding the three different types of
+ initialisation files GDB uses, system wide, home directory, and current
+ working directory. */
- if (!initialized)
- {
- struct stat homebuf, cwdbuf, s;
+class gdb_initfile_finder
+{
+public:
+ /* Constructor. Finds initialisation files named FILENAME in the home
+ directory or local (current working) directory. System initialisation
+ files are found in both SYSTEM_FILENAME and SYSTEM_DIRNAME if these
+ are not nullptr (either or both can be). The matching *_RELOCATABLE
+ flag is passed through to RELOCATE_FILE_PATH_MAYBE_IN_DATADIR.
+
+ If FILENAME starts with a '.' then when looking in the home directory
+ this first '.' can be ignored in some cases. */
+ explicit gdb_initfile_finder (const char *filename,
+ const char *system_filename,
+ bool system_filename_relocatable,
+ const char *system_dirname,
+ bool system_dirname_relocatable,
+ bool lookup_local_file)
+ {
+ struct stat s;
- if (SYSTEM_GDBINIT[0])
- {
- std::string relocated_sysgdbinit
- = relocate_gdbinit_path_maybe_in_datadir (SYSTEM_GDBINIT);
- if (!relocated_sysgdbinit.empty ()
- && stat (relocated_sysgdbinit.c_str (), &s) == 0)
- sysgdbinit = relocated_sysgdbinit;
- }
+ if (system_filename != nullptr && system_filename[0] != '\0')
+ {
+ std::string relocated_filename
+ = relocate_file_path_maybe_in_datadir (system_filename,
+ system_filename_relocatable);
+ if (!relocated_filename.empty ()
+ && stat (relocated_filename.c_str (), &s) == 0)
+ m_system_files.push_back (relocated_filename);
+ }
- const char *homedir = getenv ("HOME");
+ if (system_dirname != nullptr && system_dirname[0] != '\0')
+ {
+ std::string relocated_dirname
+ = relocate_file_path_maybe_in_datadir (system_dirname,
+ system_dirname_relocatable);
+ if (!relocated_dirname.empty ())
+ {
+ gdb_dir_up dir (opendir (relocated_dirname.c_str ()));
+ if (dir != nullptr)
+ {
+ std::vector<std::string> files;
+ while (true)
+ {
+ struct dirent *ent = readdir (dir.get ());
+ if (ent == nullptr)
+ break;
+ std::string name (ent->d_name);
+ if (name == "." || name == "..")
+ continue;
+ /* ent->d_type is not available on all systems
+ (e.g. mingw, Solaris), so we have to call stat(). */
+ std::string tmp_filename
+ = relocated_dirname + SLASH_STRING + name;
+ if (stat (tmp_filename.c_str (), &s) != 0
+ || !S_ISREG (s.st_mode))
+ continue;
+ const struct extension_language_defn *extlang
+ = get_ext_lang_of_file (tmp_filename.c_str ());
+ /* We effectively don't support "set script-extension
+ off/soft", because we are loading system init files
+ here, so it does not really make sense to depend on
+ a setting. */
+ if (extlang != nullptr && ext_lang_present_p (extlang))
+ files.push_back (std::move (tmp_filename));
+ }
+ std::sort (files.begin (), files.end ());
+ m_system_files.insert (m_system_files.end (),
+ files.begin (), files.end ());
+ }
+ }
+ }
/* If the .gdbinit file in the current directory is the same as
the $HOME/.gdbinit file, it should not be sourced. homebuf
are zero in case one of them fails (this guarantees that they
won't match if either exists). */
- memset (&homebuf, 0, sizeof (struct stat));
- memset (&cwdbuf, 0, sizeof (struct stat));
+ struct stat homebuf, cwdbuf;
+ memset (&homebuf, 0, sizeof (struct stat));
+ memset (&cwdbuf, 0, sizeof (struct stat));
- if (homedir)
- {
- homeinit = std::string (homedir) + SLASH_STRING + GDBINIT;
- if (stat (homeinit.c_str (), &homebuf) != 0)
- {
- homeinit = "";
- }
- }
+ m_home_file = find_gdb_home_config_file (filename, &homebuf);
- if (stat (GDBINIT, &cwdbuf) == 0)
- {
- if (homeinit.empty ()
- || memcmp ((char *) &homebuf, (char *) &cwdbuf,
- sizeof (struct stat)))
- localinit = GDBINIT;
- }
-
- initialized = 1;
- }
+ if (lookup_local_file && stat (filename, &cwdbuf) == 0)
+ {
+ if (m_home_file.empty ()
+ || memcmp ((char *) &homebuf, (char *) &cwdbuf,
+ sizeof (struct stat)))
+ m_local_file = filename;
+ }
+ }
+
+ DISABLE_COPY_AND_ASSIGN (gdb_initfile_finder);
- *system_gdbinit = sysgdbinit;
- *home_gdbinit = homeinit;
- *local_gdbinit = localinit;
+ /* Return a list of system initialisation files. The list could be
+ empty. */
+ const std::vector<std::string> &system_files () const
+ { return m_system_files; }
+
+ /* Return the path to the home initialisation file. The string can be
+ empty if there is no such file. */
+ const std::string &home_file () const
+ { return m_home_file; }
+
+ /* Return the path to the local initialisation file. The string can be
+ empty if there is no such file. */
+ const std::string &local_file () const
+ { return m_local_file; }
+
+private:
+
+ /* Vector of all system init files in the order they should be processed.
+ Could be empty. */
+ std::vector<std::string> m_system_files;
+
+ /* Initialization file from the home directory. Could be the empty
+ string if there is no such file found. */
+ std::string m_home_file;
+
+ /* Initialization file from the current working directory. Could be the
+ empty string if there is no such file found. */
+ std::string m_local_file;
+};
+
+/* Compute the locations of init files that GDB should source and return
+ them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. The SYSTEM_GDBINIT
+ can be returned as an empty vector, and HOME_GDBINIT and LOCAL_GDBINIT
+ can be returned as empty strings if there is no init file of that
+ type. */
+
+static void
+get_init_files (std::vector<std::string> *system_gdbinit,
+ std::string *home_gdbinit,
+ std::string *local_gdbinit)
+{
+ /* Cache the file lookup object so we only actually search for the files
+ once. */
+ static gdb::optional<gdb_initfile_finder> init_files;
+ if (!init_files.has_value ())
+ init_files.emplace (GDBINIT, SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE,
+ SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE,
+ true);
+
+ *system_gdbinit = init_files->system_files ();
+ *home_gdbinit = init_files->home_file ();
+ *local_gdbinit = init_files->local_file ();
}
-/* Try to set up an alternate signal stack for SIGSEGV handlers.
- This allows us to handle SIGSEGV signals generated when the
- normal process stack is exhausted. If this stack is not set
- up (sigaltstack is unavailable or fails) and a SIGSEGV is
- generated when the normal stack is exhausted then the program
- will behave as though no SIGSEGV handler was installed. */
+/* Compute the location of the early init file GDB should source and return
+ it in HOME_GDBEARLYINIT. HOME_GDBEARLYINIT could be returned as an
+ empty string if there is no early init file found. */
static void
-setup_alternate_signal_stack (void)
+get_earlyinit_files (std::string *home_gdbearlyinit)
{
-#ifdef HAVE_SIGALTSTACK
- stack_t ss;
+ /* Cache the file lookup object so we only actually search for the files
+ once. */
+ static gdb::optional<gdb_initfile_finder> init_files;
+ if (!init_files.has_value ())
+ init_files.emplace (GDBEARLYINIT, nullptr, false, nullptr, false, false);
+
+ *home_gdbearlyinit = init_files->home_file ();
+}
- /* FreeBSD versions older than 11.0 use char * for ss_sp instead of
- void *. This cast works with both types. */
- ss.ss_sp = (char *) xmalloc (SIGSTKSZ);
- ss.ss_size = SIGSTKSZ;
- ss.ss_flags = 0;
+/* Start up the event loop. This is the entry point to the event loop
+ from the command loop. */
- sigaltstack(&ss, NULL);
-#endif
+static void
+start_event_loop ()
+{
+ /* Loop until there is nothing to do. This is the entry point to
+ the event loop engine. gdb_do_one_event will process one event
+ for each invocation. It blocks waiting for an event and then
+ processes it. */
+ while (1)
+ {
+ int result = 0;
+
+ try
+ {
+ result = gdb_do_one_event ();
+ }
+ catch (const gdb_exception &ex)
+ {
+ exception_print (gdb_stderr, ex);
+
+ /* If any exception escaped to here, we better enable
+ stdin. Otherwise, any command that calls async_disable_stdin,
+ and then throws, will leave stdin inoperable. */
+ SWITCH_THRU_ALL_UIS ()
+ {
+ async_enable_stdin ();
+ }
+ /* If we long-jumped out of do_one_event, we probably didn't
+ get around to resetting the prompt, which leaves readline
+ in a messed-up state. Reset it here. */
+ current_ui->prompt_state = PROMPT_NEEDED;
+ gdb::observers::command_error.notify ();
+ /* This call looks bizarre, but it is required. If the user
+ entered a command that caused an error,
+ after_char_processing_hook won't be called from
+ rl_callback_read_char_wrapper. Using a cleanup there
+ won't work, since we want this function to be called
+ after a new prompt is printed. */
+ if (after_char_processing_hook)
+ (*after_char_processing_hook) ();
+ /* Maybe better to set a flag to be checked somewhere as to
+ whether display the prompt or not. */
+ }
+
+ if (result < 0)
+ break;
+ }
+
+ /* We are done with the event loop. There are no more event sources
+ to listen to. So we exit GDB. */
+ return;
}
/* Call command_loop. */
static int
catch_command_errors (catch_command_errors_const_ftype command,
- const char *arg, int from_tty)
+ const char *arg, int from_tty,
+ bool do_bp_actions = false)
{
try
{
command (arg, from_tty);
maybe_wait_sync_command_done (was_sync);
+
+ /* Do any commands attached to breakpoint we stopped at. */
+ if (do_bp_actions)
+ bpstat_do_actions ();
}
catch (const gdb_exception &e)
{
/* Option type -ix. */
CMDARG_INIT_FILE,
-
+
/* Option type -iex. */
- CMDARG_INIT_COMMAND
+ CMDARG_INIT_COMMAND,
+
+ /* Option type -eix. */
+ CMDARG_EARLYINIT_FILE,
+
+ /* Option type -eiex. */
+ CMDARG_EARLYINIT_COMMAND
};
/* Arguments of --command option and its counterpart. */
char *string;
};
+/* From CMDARG_VEC execute command files (matching FILE_TYPE) or commands
+ (matching CMD_TYPE). Update the value in *RET if and scripts or
+ commands are executed. */
+
+static void
+execute_cmdargs (const std::vector<struct cmdarg> *cmdarg_vec,
+ cmdarg_kind file_type, cmdarg_kind cmd_type,
+ int *ret)
+{
+ for (const auto &cmdarg_p : *cmdarg_vec)
+ {
+ if (cmdarg_p.type == file_type)
+ *ret = catch_command_errors (source_script, cmdarg_p.string,
+ !batch_flag);
+ else if (cmdarg_p.type == cmd_type)
+ *ret = catch_command_errors (execute_command, cmdarg_p.string,
+ !batch_flag, true);
+ }
+}
+
static void
captured_main_1 (struct captured_main_args *context)
{
main_ui = new ui (stdin, stdout, stderr);
current_ui = main_ui;
- gdb_stdtargerr = gdb_stderr; /* for moment */
- gdb_stdtargin = gdb_stdin; /* for moment */
+ gdb_stdtarg = gdb_stderr;
+ gdb_stdtargerr = gdb_stderr;
+ gdb_stdtargin = gdb_stdin;
if (bfd_init () != BFD_INIT_MAGIC)
error (_("fatal error: libbfd ABI mismatch"));
/* Prefix warning messages with the command name. */
gdb::unique_xmalloc_ptr<char> tmp_warn_preprint
- (xstrprintf ("%s: warning: ", gdb_program_name));
+ = xstrprintf ("%s: warning: ", gdb_program_name);
warning_pre_print = tmp_warn_preprint.get ();
current_directory = getcwd (NULL, 0);
perror_warning_with_name (_("error finding working directory"));
/* Set the sysroot path. */
- gdb_sysroot
- = xstrdup (relocate_gdb_directory (TARGET_SYSTEM_ROOT,
- TARGET_SYSTEM_ROOT_RELOCATABLE).c_str ());
+ gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
+ TARGET_SYSTEM_ROOT_RELOCATABLE);
- if (*gdb_sysroot == '\0')
- {
- xfree (gdb_sysroot);
- gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX);
- }
+ if (gdb_sysroot.empty ())
+ gdb_sysroot = TARGET_SYSROOT_PREFIX;
debug_file_directory
- = xstrdup (relocate_gdb_directory (DEBUGDIR,
- DEBUGDIR_RELOCATABLE).c_str ());
-
- gdb_datadir
- = xstrdup (relocate_gdb_directory (GDB_DATADIR,
- GDB_DATADIR_RELOCATABLE).c_str ());
+ = relocate_gdb_directory (DEBUGDIR, DEBUGDIR_RELOCATABLE);
-#ifdef WITH_PYTHON_PATH
- {
- /* For later use in helping Python find itself. */
- char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", (char *) NULL);
+ gdb_datadir = relocate_gdb_directory (GDB_DATADIR,
+ GDB_DATADIR_RELOCATABLE);
- python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE);
- xfree (tmp);
- }
+#ifdef WITH_PYTHON_LIBDIR
+ python_libdir = relocate_gdb_directory (WITH_PYTHON_LIBDIR,
+ PYTHON_LIBDIR_RELOCATABLE);
#endif
#ifdef RELOC_SRCDIR
this captured main, or one specified by the user at start up, or
the console. Initialize the interpreter to the one requested by
the application. */
- interpreter_p = xstrdup (context->interpreter_p);
+ interpreter_p = context->interpreter_p;
/* Parse arguments and options. */
{
OPT_WINDOWS,
OPT_IX,
OPT_IEX,
+ OPT_EIX,
+ OPT_EIEX,
OPT_READNOW,
OPT_READNEVER
};
static struct option long_options[] =
{
{"tui", no_argument, 0, OPT_TUI},
- {"dbx", no_argument, &dbx_commands, 1},
{"readnow", no_argument, NULL, OPT_READNOW},
{"readnever", no_argument, NULL, OPT_READNEVER},
{"r", no_argument, NULL, OPT_READNOW},
{"init-eval-command", required_argument, 0, OPT_IEX},
{"ix", required_argument, 0, OPT_IX},
{"iex", required_argument, 0, OPT_IEX},
+ {"early-init-command", required_argument, 0, OPT_EIX},
+ {"early-init-eval-command", required_argument, 0, OPT_EIEX},
+ {"eix", required_argument, 0, OPT_EIX},
+ {"eiex", required_argument, 0, OPT_EIEX},
#ifdef GDBTK
{"tclcommand", required_argument, 0, 'z'},
{"enable-external-editor", no_argument, 0, 'y'},
case OPT_TUI:
/* --tui is equivalent to -i=tui. */
#ifdef TUI
- xfree (interpreter_p);
- interpreter_p = xstrdup (INTERP_TUI);
+ interpreter_p = INTERP_TUI;
#else
error (_("%s: TUI mode is not supported"), gdb_program_name);
#endif
break;
case OPT_WINDOWS:
/* FIXME: cagney/2003-03-01: Not sure if this option is
- actually useful, and if it is, what it should do. */
+ actually useful, and if it is, what it should do. */
#ifdef GDBTK
/* --windows is equivalent to -i=insight. */
- xfree (interpreter_p);
- interpreter_p = xstrdup (INTERP_INSIGHT);
+ interpreter_p = INTERP_INSIGHT;
#endif
break;
case OPT_NOWINDOWS:
/* -nw is equivalent to -i=console. */
- xfree (interpreter_p);
- interpreter_p = xstrdup (INTERP_CONSOLE);
+ interpreter_p = INTERP_CONSOLE;
break;
case 'f':
annotation_level = 1;
case OPT_IEX:
cmdarg_vec.emplace_back (CMDARG_INIT_COMMAND, optarg);
break;
+ case OPT_EIX:
+ cmdarg_vec.emplace_back (CMDARG_EARLYINIT_FILE, optarg);
+ break;
+ case OPT_EIEX:
+ cmdarg_vec.emplace_back (CMDARG_EARLYINIT_COMMAND, optarg);
+ break;
case 'B':
batch_flag = batch_silent = 1;
gdb_stdout = new null_file ();
#ifdef GDBTK
case 'z':
{
- extern int gdbtk_test (char *);
-
if (!gdbtk_test (optarg))
error (_("%s: unable to load tclcommand file \"%s\""),
gdb_program_name, optarg);
{
/* Set the external editor commands when gdb is farming out files
to be edited by another program. */
- extern char *external_editor_command;
-
external_editor_command = xstrdup (optarg);
break;
}
#endif /* GDBTK */
case 'i':
- xfree (interpreter_p);
- interpreter_p = xstrdup (optarg);
+ interpreter_p = optarg;
break;
case 'd':
dirarg.push_back (optarg);
else
baud_rate = rate;
}
- break;
+ break;
case 'l':
{
int timeout;
save_original_signals_state (quiet);
/* Try to set up an alternate signal stack for SIGSEGV handlers. */
- setup_alternate_signal_stack ();
+ gdb::alternate_signal_stack signal_stack;
/* Initialize all files. */
- gdb_init (gdb_program_name);
+ gdb_init ();
+
+ /* Process early init files and early init options from the command line. */
+ if (!inhibit_gdbinit)
+ {
+ std::string home_gdbearlyinit;
+ get_earlyinit_files (&home_gdbearlyinit);
+ if (!home_gdbearlyinit.empty () && !inhibit_home_gdbinit)
+ ret = catch_command_errors (source_script,
+ home_gdbearlyinit.c_str (), 0);
+ }
+ execute_cmdargs (&cmdarg_vec, CMDARG_EARLYINIT_FILE,
+ CMDARG_EARLYINIT_COMMAND, &ret);
+
+ /* Initialize the extension languages. */
+ ext_lang_initialization ();
+
+ /* Recheck if we're starting up quietly after processing the startup
+ scripts and commands. */
+ if (!quiet)
+ quiet = check_quiet_mode ();
/* Now that gdb_init has created the initial inferior, we're in
position to set args for that inferior. */
/* Any argument left on the command line is unexpected and
will be ignored. Inform the user. */
if (optind < argc)
- fprintf_unfiltered (gdb_stderr,
- _("Excess command line "
- "arguments ignored. (%s%s)\n"),
- argv[optind],
- (optind == argc - 1) ? "" : " ...");
+ gdb_printf (gdb_stderr,
+ _("Excess command line "
+ "arguments ignored. (%s%s)\n"),
+ argv[optind],
+ (optind == argc - 1) ? "" : " ...");
}
/* Lookup gdbinit files. Note that the gdbinit file name may be
- overriden during file initialization, so get_init_files should be
+ overridden during file initialization, so get_init_files should be
called after gdb_init. */
- std::string system_gdbinit;
+ std::vector<std::string> system_gdbinit;
std::string home_gdbinit;
std::string local_gdbinit;
get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
if (print_version)
{
print_gdb_version (gdb_stdout, false);
- wrap_here ("");
- printf_filtered ("\n");
+ gdb_printf ("\n");
exit (0);
}
if (print_help)
{
print_gdb_help (gdb_stdout);
- fputs_unfiltered ("\n", gdb_stdout);
exit (0);
}
if (print_configuration)
{
print_gdb_configuration (gdb_stdout);
- wrap_here ("");
- printf_filtered ("\n");
+ gdb_printf ("\n");
exit (0);
}
- /* FIXME: cagney/2003-02-03: The big hack (part 1 of 2) that lets
- GDB retain the old MI1 interpreter startup behavior. Output the
- copyright message before the interpreter is installed. That way
- it isn't encapsulated in MI output. */
- if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
- {
- /* Print all the junk at the top, with trailing "..." if we are
- about to read a symbol file (possibly slowly). */
- print_gdb_version (gdb_stdout, true);
- if (symarg)
- printf_filtered ("..");
- wrap_here ("");
- printf_filtered ("\n");
- gdb_flush (gdb_stdout); /* Force to screen during slow
- operations. */
- }
-
/* Install the default UI. All the interpreters should have had a
look at things by now. Initialize the default interpreter. */
- set_top_level_interpreter (interpreter_p);
+ set_top_level_interpreter (interpreter_p.c_str ());
- /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
- GDB retain the old MI1 interpreter startup behavior. Output the
- copyright message after the interpreter is installed when it is
- any sane interpreter. */
- if (!quiet && !current_interp_named_p (INTERP_MI1))
+ if (!quiet)
{
/* Print all the junk at the top, with trailing "..." if we are
- about to read a symbol file (possibly slowly). */
+ about to read a symbol file (possibly slowly). */
print_gdb_version (gdb_stdout, true);
if (symarg)
- printf_filtered ("..");
- wrap_here ("");
- printf_filtered ("\n");
+ gdb_printf ("..");
+ gdb_printf ("\n");
gdb_flush (gdb_stdout); /* Force to screen during slow
operations. */
}
processed; it sets global parameters, which are independent of
what file you are debugging or what directory you are in. */
if (!system_gdbinit.empty () && !inhibit_gdbinit)
- ret = catch_command_errors (source_script, system_gdbinit.c_str (), 0);
+ {
+ for (const std::string &file : system_gdbinit)
+ ret = catch_command_errors (source_script, file.c_str (), 0);
+ }
/* Read and execute $HOME/.gdbinit file, if it exists. This is done
*before* all the command line arguments are processed; it sets
ret = catch_command_errors (source_script, home_gdbinit.c_str (), 0);
/* Process '-ix' and '-iex' options early. */
- for (i = 0; i < cmdarg_vec.size (); i++)
- {
- const struct cmdarg &cmdarg_p = cmdarg_vec[i];
-
- switch (cmdarg_p.type)
- {
- case CMDARG_INIT_FILE:
- ret = catch_command_errors (source_script, cmdarg_p.string,
- !batch_flag);
- break;
- case CMDARG_INIT_COMMAND:
- ret = catch_command_errors (execute_command, cmdarg_p.string,
- !batch_flag);
- break;
- }
- }
+ execute_cmdargs (&cmdarg_vec, CMDARG_INIT_FILE, CMDARG_INIT_COMMAND, &ret);
/* Now perform all the actions indicated by the arguments. */
if (cdarg != NULL)
&& strcmp (execarg, symarg) == 0)
{
/* The exec file and the symbol-file are the same. If we can't
- open it, better only print one error message.
- catch_command_errors returns non-zero on success! */
+ open it, better only print one error message.
+ catch_command_errors returns non-zero on success! */
ret = catch_command_errors (exec_file_attach, execarg,
!batch_flag);
if (ret != 0)
}
if (ttyarg != NULL)
- set_inferior_io_terminal (ttyarg);
+ current_inferior ()->set_tty (ttyarg);
/* Error messages should no longer be distinguished with extra output. */
warning_pre_print = _("warning: ");
auto_load_local_gdbinit_pathname
= gdb_realpath (local_gdbinit.c_str ()).release ();
- if (!inhibit_gdbinit && auto_load_local_gdbinit
- && file_is_auto_load_safe (local_gdbinit.c_str (),
- _("auto-load: Loading .gdbinit "
- "file \"%s\".\n"),
- local_gdbinit.c_str ()))
+ if (!inhibit_gdbinit && auto_load_local_gdbinit)
{
- auto_load_local_gdbinit_loaded = 1;
+ auto_load_debug_printf ("Loading .gdbinit file \"%s\".",
+ local_gdbinit.c_str ());
+
+ if (file_is_auto_load_safe (local_gdbinit.c_str ()))
+ {
+ auto_load_local_gdbinit_loaded = 1;
- ret = catch_command_errors (source_script, local_gdbinit.c_str (), 0);
+ ret = catch_command_errors (source_script, local_gdbinit.c_str (), 0);
+ }
}
}
load_auto_scripts_for_objfile (objfile);
/* Process '-x' and '-ex' options. */
- for (i = 0; i < cmdarg_vec.size (); i++)
- {
- const struct cmdarg &cmdarg_p = cmdarg_vec[i];
-
- switch (cmdarg_p.type)
- {
- case CMDARG_FILE:
- ret = catch_command_errors (source_script, cmdarg_p.string,
- !batch_flag);
- break;
- case CMDARG_COMMAND:
- ret = catch_command_errors (execute_command, cmdarg_p.string,
- !batch_flag);
- break;
- }
- }
+ execute_cmdargs (&cmdarg_vec, CMDARG_FILE, CMDARG_COMMAND, &ret);
/* Read in the old history after all the command files have been
read. */
static void
print_gdb_help (struct ui_file *stream)
{
- std::string system_gdbinit;
+ std::vector<std::string> system_gdbinit;
std::string home_gdbinit;
std::string local_gdbinit;
+ std::string home_gdbearlyinit;
get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
+ get_earlyinit_files (&home_gdbearlyinit);
/* Note: The options in the list below are only approximately sorted
in the alphabetical order, so as to group closely related options
together. */
- fputs_unfiltered (_("\
+ gdb_puts (_("\
This is the GNU debugger. Usage:\n\n\
gdb [options] [executable-file [core-file or process-id]]\n\
gdb [options] --args executable-file [inferior-arguments ...]\n\n\
"), stream);
- fputs_unfiltered (_("\
+ gdb_puts (_("\
Selection of debuggee and its files:\n\n\
- --args Arguments after executable-file are passed to inferior\n\
+ --args Arguments after executable-file are passed to inferior.\n\
--core=COREFILE Analyze the core dump COREFILE.\n\
--exec=EXECFILE Use EXECFILE as the executable.\n\
--pid=PID Attach to running process PID.\n\
--readnever Do not read symbol files.\n\
--write Set writing into executable and core files.\n\n\
"), stream);
- fputs_unfiltered (_("\
+ gdb_puts (_("\
Initial commands and command files:\n\n\
--command=FILE, -x Execute GDB commands from FILE.\n\
--init-command=FILE, -ix\n\
- Like -x but execute commands before loading inferior.\n\
+ Like -x but execute commands before loading inferior.\n\
--eval-command=COMMAND, -ex\n\
- Execute a single GDB command.\n\
- May be used multiple times and in conjunction\n\
- with --command.\n\
+ Execute a single GDB command.\n\
+ May be used multiple times and in conjunction\n\
+ with --command.\n\
--init-eval-command=COMMAND, -iex\n\
- Like -ex but before loading inferior.\n\
+ Like -ex but before loading inferior.\n\
--nh Do not read ~/.gdbinit.\n\
--nx Do not read any .gdbinit files in any directory.\n\n\
"), stream);
- fputs_unfiltered (_("\
+ gdb_puts (_("\
Output and user interface control:\n\n\
--fullname Output information used by emacs-GDB interface.\n\
--interpreter=INTERP\n\
- Select a specific interpreter / user interface\n\
+ Select a specific interpreter / user interface.\n\
--tty=TTY Use TTY for input/output by the program being debugged.\n\
-w Use the GUI interface.\n\
--nw Do not use the GUI interface.\n\
"), stream);
#if defined(TUI)
- fputs_unfiltered (_("\
+ gdb_puts (_("\
--tui Use a terminal user interface.\n\
"), stream);
#endif
- fputs_unfiltered (_("\
- --dbx DBX compatibility mode.\n\
+ gdb_puts (_("\
-q, --quiet, --silent\n\
- Do not print version number on startup.\n\n\
+ Do not print version number on startup.\n\n\
"), stream);
- fputs_unfiltered (_("\
+ gdb_puts (_("\
Operating modes:\n\n\
--batch Exit after processing options.\n\
--batch-silent Like --batch, but suppress all gdb stdout output.\n\
--return-child-result\n\
- GDB exit code will be the child's exit code.\n\
+ GDB exit code will be the child's exit code.\n\
--configuration Print details about GDB configuration and then exit.\n\
--help Print this message and then exit.\n\
--version Print version information and then exit.\n\n\
Other options:\n\n\
--cd=DIR Change current directory to DIR.\n\
--data-directory=DIR, -D\n\
- Set GDB's data-directory to DIR.\n\
+ Set GDB's data-directory to DIR.\n\
+"), stream);
+ gdb_puts (_("\n\
+At startup, GDB reads the following early init files and executes their\n\
+commands:\n\
"), stream);
- fputs_unfiltered (_("\n\
+ if (!home_gdbearlyinit.empty ())
+ gdb_printf (stream, _("\
+ * user-specific early init file: %s\n\
+"), home_gdbearlyinit.c_str ());
+ if (home_gdbearlyinit.empty ())
+ gdb_printf (stream, _("\
+ None found.\n"));
+ gdb_puts (_("\n\
At startup, GDB reads the following init files and executes their commands:\n\
"), stream);
if (!system_gdbinit.empty ())
- fprintf_unfiltered (stream, _("\
- * system-wide init file: %s\n\
-"), system_gdbinit.c_str ());
+ {
+ std::string output;
+ for (size_t idx = 0; idx < system_gdbinit.size (); ++idx)
+ {
+ output += system_gdbinit[idx];
+ if (idx < system_gdbinit.size () - 1)
+ output += ", ";
+ }
+ gdb_printf (stream, _("\
+ * system-wide init files: %s\n\
+"), output.c_str ());
+ }
if (!home_gdbinit.empty ())
- fprintf_unfiltered (stream, _("\
+ gdb_printf (stream, _("\
* user-specific init file: %s\n\
"), home_gdbinit.c_str ());
if (!local_gdbinit.empty ())
- fprintf_unfiltered (stream, _("\
+ gdb_printf (stream, _("\
* local init file (see also 'set auto-load local-gdbinit'): ./%s\n\
"), local_gdbinit.c_str ());
- fputs_unfiltered (_("\n\
+ if (system_gdbinit.empty () && home_gdbinit.empty ()
+ && local_gdbinit.empty ())
+ gdb_printf (stream, _("\
+ None found.\n"));
+ gdb_puts (_("\n\
For more information, type \"help\" from within GDB, or consult the\n\
GDB manual (available as on-line info or a printed manual).\n\
"), stream);
if (REPORT_BUGS_TO[0] && stream == gdb_stdout)
- fprintf_unfiltered (stream, _("\
-Report bugs to \"%s\".\n\
-"), REPORT_BUGS_TO);
+ gdb_printf (stream, _("\n\
+Report bugs to %ps.\n\
+"), styled_string (file_name_style.style (), REPORT_BUGS_TO));
+ if (stream == gdb_stdout)
+ gdb_printf (stream, _("\n\
+You can ask GDB-related questions on the GDB users mailing list\n\
+(gdb@sourceware.org) or on GDB's IRC channel (#gdb on Freenode).\n"));
}