public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCHv2 0/3] Adding startup files to GDB
@ 2021-01-26  9:48 Andrew Burgess
  2021-01-26  9:48 ` [PATCHv2 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Andrew Burgess @ 2021-01-26  9:48 UTC (permalink / raw)
  To: gdb-patches

This series is a revised version of this series:

   https://sourceware.org/pipermail/gdb-patches/2020-October/172422.html

Which in turn draws heavily from work done by Tom:

   https://sourceware.org/pipermail/gdb-patches/2020-June/169821.html

The biggest change from the original series is the removal of
everything related to auto-saving of startup options.  The removal
doesn't mean this feature couldn't be added back in the future, but it
felt like that was a separate piece of work from the core idea of
adding a mechanism to control how GDB starts up.

I also simplified the startup file look up, startup files can now only
appear in the users home directory (following GDB's usual home
directory lookup logic).

All feedback welcome.

Thanks,
Andrew


---

Andrew Burgess (2):
  gdb: refactor the initialization file lookup code
  gdb: process startup files and startup command line options

Tom Tromey (1):
  gdb: add "set startup-quietly" command

 gdb/ChangeLog                           |  33 +++
 gdb/NEWS                                |  18 ++
 gdb/config.in                           |   3 +
 gdb/configure                           |   6 +
 gdb/configure.ac                        |   3 +
 gdb/doc/ChangeLog                       |  14 ++
 gdb/doc/gdb.texinfo                     | 120 ++++++++++-
 gdb/main.c                              | 257 ++++++++++++++++++------
 gdb/testsuite/ChangeLog                 |  11 +
 gdb/testsuite/gdb.base/startup-file.c   |  22 ++
 gdb/testsuite/gdb.base/startup-file.exp | 149 ++++++++++++++
 gdb/testsuite/lib/gdb-utils.exp         |   1 +
 gdb/top.c                               |  33 +++
 gdb/top.h                               |   5 +
 14 files changed, 602 insertions(+), 73 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/startup-file.c
 create mode 100644 gdb/testsuite/gdb.base/startup-file.exp

-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv2 1/3] gdb: refactor the initialization file lookup code
  2021-01-26  9:48 [PATCHv2 0/3] Adding startup files to GDB Andrew Burgess
@ 2021-01-26  9:48 ` Andrew Burgess
  2021-01-26 15:09   ` Simon Marchi
  2021-01-26  9:48 ` [PATCHv2 2/3] gdb: process startup files and startup command line options Andrew Burgess
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-01-26  9:48 UTC (permalink / raw)
  To: gdb-patches

In preparation for the next patch, which adds startup files, this
commit refactors the code for looking up the initialization files so
that the code can be more easily reused in the next commit.

There should be no user visible changes after this commit.

gdb/ChangeLog:

	* main.c (relocate_gdbinit_path_maybe_in_datadir): Rename to...
	(relocate_file_path_maybe_in_datadir): ...this.
	(class gdb_initfile_finder): New class.
	(get_init_files): Now uses gdb_initfile_finder.
	(print_gdb_help): Print 'None found' when there are no init files.
---
 gdb/ChangeLog |   8 +++
 gdb/main.c    | 190 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 135 insertions(+), 63 deletions(-)

diff --git a/gdb/main.c b/gdb/main.c
index 331e3a50acf..2d2fded7158 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -203,8 +203,8 @@ relocate_gdb_directory (const char *initial, bool relocatable)
    otherwise.  */
 
 static std::string
-relocate_gdbinit_path_maybe_in_datadir (const std::string &file,
-					bool relocatable)
+relocate_file_path_maybe_in_datadir (const std::string &file,
+				     bool relocatable)
 {
   size_t datadir_len = strlen (GDB_DATADIR);
 
@@ -233,45 +233,52 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string &file,
     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::vector<std::string> *system_gdbinit,
-		std::string *home_gdbinit,
-		std::string *local_gdbinit)
+/* 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.  */
+
+class gdb_initfile_finder
 {
-  static std::vector<std::string> sysgdbinit;
-  static std::string homeinit;
-  static std::string localinit;
-  static int initialized = 0;
+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 (!initialized)
-    {
-      struct stat homebuf, cwdbuf, s;
+    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);
+      }
 
-      if (SYSTEM_GDBINIT[0])
-	{
-	  std::string relocated_sysgdbinit
-	    = relocate_gdbinit_path_maybe_in_datadir
-		(SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE);
-	  if (!relocated_sysgdbinit.empty ()
-	      && stat (relocated_sysgdbinit.c_str (), &s) == 0)
-	    sysgdbinit.push_back (relocated_sysgdbinit);
-	}
-      if (SYSTEM_GDBINIT_DIR[0])
-	{
-	  std::string relocated_gdbinit_dir
-	    = relocate_gdbinit_path_maybe_in_datadir
-		(SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE);
-	  if (!relocated_gdbinit_dir.empty ()) {
-	    gdb_dir_up dir (opendir (relocated_gdbinit_dir.c_str ()));
+    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;
-		for (;;)
+		while (true)
 		  {
 		    struct dirent *ent = readdir (dir.get ());
 		    if (ent == nullptr)
@@ -279,28 +286,28 @@ get_init_files (std::vector<std::string> *system_gdbinit,
 		    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 filename
-		      = relocated_gdbinit_dir + SLASH_STRING + name;
-		    if (stat (filename.c_str (), &s) != 0
+		    /* 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 (filename.c_str ());
+		      = 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.  */
+		       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 (filename));
+		      files.push_back (std::move (tmp_filename));
 		  }
 		std::sort (files.begin (), files.end ());
-		sysgdbinit.insert (sysgdbinit.end (),
-				   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
@@ -308,25 +315,78 @@ get_init_files (std::vector<std::string> *system_gdbinit,
 	 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));
 
-      homeinit = find_gdb_home_config_file (GDBINIT, &homebuf);
+    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;
-	}
+    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;
+      }
+  }
 
-      initialized = 1;
-    }
+  DISABLE_COPY_AND_ASSIGN (gdb_initfile_finder);
+
+  /* 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;
 
-  *system_gdbinit = sysgdbinit;
-  *home_gdbinit = homeinit;
-  *local_gdbinit = localinit;
+  /* 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 std::unique_ptr<gdb_initfile_finder> init_files;
+  if (init_files == nullptr)
+    init_files = std::unique_ptr<gdb_initfile_finder>
+      (new gdb_initfile_finder (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 ();
 }
 
 /* Start up the event loop.  This is the entry point to the event loop
@@ -1375,6 +1435,10 @@ At startup, GDB reads the following init files and executes their commands:\n\
     fprintf_unfiltered (stream, _("\
    * local init file (see also 'set auto-load local-gdbinit'): ./%s\n\
 "), local_gdbinit.c_str ());
+  if (system_gdbinit.empty () && home_gdbinit.empty ()
+      && local_gdbinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   None found.\n"));
   fputs_unfiltered (_("\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\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv2 2/3] gdb: process startup files and startup command line options
  2021-01-26  9:48 [PATCHv2 0/3] Adding startup files to GDB Andrew Burgess
  2021-01-26  9:48 ` [PATCHv2 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
@ 2021-01-26  9:48 ` Andrew Burgess
  2021-01-26 15:22   ` Eli Zaretskii
  2021-01-26 15:30   ` Simon Marchi
  2021-01-26  9:48 ` [PATCHv2 3/3] gdb: add "set startup-quietly" command Andrew Burgess
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  3 siblings, 2 replies; 20+ messages in thread
From: Andrew Burgess @ 2021-01-26  9:48 UTC (permalink / raw)
  To: gdb-patches

Adds the ability to process commands at a new phase during GDB's
startup.  This phase is earlier than the current initialisation file
processing, before GDB has produced any output.

The number of commands that can be processed at this early stage will
be limited, and it is expected that the only commands that would be
processed at this stage will relate to some of the fundamentals of how
GDB starts up.

Currently the only commands that it makes sense to add to this startup
file are those like 'set style version ....' as the version string is
displayed during startup before the standard initialization files are
parsed.  As such this commit fully resolved bug cli/25956.

This commit adds a mechanism to find these startup files as well as
some corresponding command line flags.

The startup files that GDB will currently check for are
~/.config/gdb/gdbstartup (on Linux like systems) or ~/.gdbstartup if
the former is not found.

The output of 'gdb --help' has been extended to include a list of the
startup files being processed.

gdb/ChangeLog:

	PR cli/25956
	* NEWS: Mention new startup files and command line options.
	* config.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: Define GDBSTARTUP.
	* main.c (get_startup_files): New function.
	(enum cmdarg_kind): Add CMDARG_STARTUP_FILE and
	CMDARG_STARTUP_COMMAND.
	(captured_main_1): Add support for new command line flags, and for
	processing startup files.
	(print_gdb_help): Include startup files in the output.

gdb/doc/ChangeLog:

	PR cli/25956
	* gdb.texinfo (File Options): Mention new command line options.
	(Startup): Discuss when startup files are processed.
	(Initialization Files): Add description of startup files.
	(Output Styling): Update description of 'version' style.
	(gdb man): Mention startup files.

gdb/testsuite/ChangeLog:

	PR cli/25956
	* gdb.base/startup-file.c: New file.
	* gdb.base/startup-file.exp: New file.
	* lib/gdb-utils.exp (style): Handle style 'none'.
---
 gdb/ChangeLog                           |  14 +++
 gdb/NEWS                                |  12 +++
 gdb/config.in                           |   3 +
 gdb/configure                           |   6 ++
 gdb/configure.ac                        |   3 +
 gdb/doc/ChangeLog                       |   9 ++
 gdb/doc/gdb.texinfo                     | 111 ++++++++++++++++++++++--
 gdb/main.c                              |  62 ++++++++++++-
 gdb/testsuite/ChangeLog                 |   7 ++
 gdb/testsuite/gdb.base/startup-file.c   |  22 +++++
 gdb/testsuite/gdb.base/startup-file.exp | 110 +++++++++++++++++++++++
 gdb/testsuite/lib/gdb-utils.exp         |   1 +
 12 files changed, 350 insertions(+), 10 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/startup-file.c
 create mode 100644 gdb/testsuite/gdb.base/startup-file.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index d2ed28857b0..368cab5fec6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -33,6 +33,18 @@
   the use of the GNAT encoding (based on information added to the type's
   name following a GNAT-specific format).
 
+* GDB will now load and process commands from ~/.config/gdb/gdbstartup
+  or ~/.gdbstartup if these files are present.  These files are
+  processed earlier than any of the previous initialization files and
+  can affect parts of GDB's startup that previously had already been
+  completed before the initialization files were read, for example
+  styling of the initial GDB greeting.
+
+* GDB now has two new options "--startup-command" and
+  "--startup-eval-command" with corresponding short options "-sx" and
+  "-sex" that allow options (that would normally appear in a
+  gdbstartup file) to be passed on the command line.
+
 * New commands
 
 set debug event-loop
diff --git a/gdb/config.in b/gdb/config.in
index 14a77c661d5..5924bf008cb 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -46,6 +46,9 @@
 /* The .gdbinit filename. */
 #undef GDBINIT
 
+/* The .gdbstartup filename. */
+#undef GDBSTARTUP
+
 /* look for global separate data files in this path [DATADIR/gdb] */
 #undef GDB_DATADIR
 
diff --git a/gdb/configure b/gdb/configure
index 51b4d1921c5..a9057fab307 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -16778,6 +16778,12 @@ _ACEOF
 
 
 
+cat >>confdefs.h <<_ACEOF
+#define GDBSTARTUP ".gdbstartup"
+_ACEOF
+
+
+
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
 # except that the argument to --with-sysroot is optional.
 # --with-sysroot (or --with-sysroot=yes) sets the default sysroot path.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 618c59166e4..5daa7aef40a 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1819,6 +1819,9 @@ case $host_os in
 esac
 AC_DEFINE_UNQUOTED(GDBINIT,"$gdbinit",[The .gdbinit filename.])
 
+dnl Set the host's .gdbstartup filename
+AC_DEFINE_UNQUOTED(GDBSTARTUP,".gdbstartup",[The .gdbstartup filename.])
+
 dnl Handle optional features that can be enabled.
 
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e43819f0f70..09f64302ba6 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1040,6 +1040,22 @@
 after loading gdbinit files).
 @xref{Startup}.
 
+@item -startup-command @var{file}
+@itemx -sx @var{file}
+@cindex @code{--startup-command}
+@cindex @code{-sx}
+Execute commands from file @var{file} as early as possible during the
+initialization process, before any output is produced.
+@xref{Startup}.
+
+@item -startup-eval-command @var{command}
+@itemx -sex @var{command}
+@cindex @code{--startup-eval-command}
+@cindex @code{-sex}
+Execute a single @value{GDBN} command as early as possible during the
+initialization process, before any output is produced.
+@xref{Startup}.
+
 @item -directory @var{directory}
 @itemx -d @var{directory}
 @cindex @code{--directory}
@@ -1291,6 +1307,22 @@
 Here's the description of what @value{GDBN} does during session startup:
 
 @enumerate
+
+@item
+Performs minimal setup required to initialise basic internal state.
+
+@item
+@cindex startup file
+Read commands from the startup file (if any) in your home directory.
+For details on which commands can be used in a startup file
+@pxref{Initialization Files}.
+
+@item
+Executes commands and command files specified by the @samp{-sex} and
+@samp{-sx} command line options in their specified order.  Only a
+restricted set of commands can be used within @samp{-sex} and
+@samp{sx}, @pxref{Initialization Files} for details.
+
 @item
 Sets up the command interpreter as specified by the command line
 (@pxref{Mode Options, interpreter}).
@@ -1367,13 +1399,73 @@
 startup, in the order they will be loaded, you can use @kbd{gdb
 --help}.
 
+The files processed are split into two categories @dfn{startup files}
+and @dfn{initialization files}.
+
+The startup file is loaded as early as possible during
+@value{GDBN}'s startup, before the interpreter (@pxref{Interpreters})
+has been initialised, and before the default target (@pxref{Targets}
+is initialised.  Only @code{set} or @code{source} commands should be
+placed into a startup file, and the only @code{set} commands that
+should be used are those that control how @value{GDBN} starts up.
+Commands that should be placed into a startup file will be documented
+as such throughout this manual.  Any command that is not documented as
+being suitable for a startup file should be placed into a general
+initialization file.  Command files passed to @code{--startup-command}
+or @code{-sx} are also startup files, with the same command
+restrictions.  Only commands that can appear in a startup file shold
+be passed to @code{--startup-eval-command} or @code{-sex}.
+
+The more general initialization files are processed later after
+@value{GDBN} has finished its own internal startup process, any
+commands can be used in these files.
+
 As the system wide and home directory initialization files are
 processed before most command line options, changes to settings
 (e.g. @samp{set complaints}) can affect subsequent processing of
 command line options and operands.
 
 The following sections describe where @value{GDBN} looks for the
-initialization and the order that the files are searched for.
+startup and initialization files, and the order that the files are
+searched for.
+
+@subsubsection Home directory startup files
+
+@value{GDBN} initially looks for a startup file in the users home
+directory@footnote{On DOS/Windows systems, the home directory is the
+one pointed to by the @code{HOME} environment variable.}.  There are a
+number of locations that @value{GDBN} will search in the home
+directory, these locations are searched in order and @value{GDBN} will
+load the first file that it finds, and subsequent locations will not
+be checked.
+
+On non-Apple hosts the locations searched are:
+@itemize
+@item
+The file @file{gdb/gdbstartup} within the directory pointed to by the
+environment variable @env{XDG_CONFIG_HOME}, if it is defined.
+@item
+The file @file{.config/gdb/gdbstartup} within the directory pointed to
+by the environment variable @env{HOME}, if it is defined.
+@item
+The file @file{.gdbstartup} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+While on Apple hosts the locations searched are:
+@itemize
+@item
+The file @file{Library/Preferences/gdb/gdbstartup} within the
+directory pointed to by the environment variable @env{HOME}, if it is
+defined.
+@item
+The file @file{.gdbstartup} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+It is possible to prevent the home directory startup file from
+being loaded using the @samp{-nx} or @samp{-nh} command line options,
+@pxref{Mode Options,,Choosing Modes}.
 
 @anchor{System Wide Init Files}
 @subsubsection System wide initialization files
@@ -25794,11 +25886,10 @@
 intensity.  The version number is displayed in two places, the output
 of @command{show version}, and when @value{GDBN} starts up.
 
-Currently the version string displayed at startup is printed before
-@value{GDBN} has parsed any command line options, or parsed any
-command files, so there is currently no way to control the styling of
-this string.  However, @value{GDBN}'s @code{--quiet} command line option
-can be used to disable printing of the version string on startup.
+In order to control how @value{GDBN} styles the version number at
+startup, add the @code{set style version} family of commands to the
+startup command file (@pxref{Initialization Files,,Initialization
+Files}).
 
 @item title
 Control the styling of titles.  These are managed with the
@@ -46603,12 +46694,14 @@
 Add @var{directory} to the path to search for source files.
 
 @item -nh
-Do not execute commands from @file{~/.config/gdb/gdbinit} or
-@file{~/.gdbinit}.
+Do not execute commands from @file{~/.config/gdb/gdbinit},
+@file{~/.gdbinit}, @file{~/.config/gdb/gdbstartup}, or
+@file{~/.gdbstartup}
 
 @item -nx
 @itemx -n
-Do not execute commands from any @file{.gdbinit} initialization files.
+Do not execute commands from any @file{.gdbinit} or @file{.gdbstartup}
+initialization files.
 
 @item -quiet
 @itemx -q
diff --git a/gdb/main.c b/gdb/main.c
index 2d2fded7158..fe1ca27c255 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -389,6 +389,24 @@ get_init_files (std::vector<std::string> *system_gdbinit,
   *local_gdbinit = init_files->local_file ();
 }
 
+/* Compute the location of the startup file GDB should source and return
+   it in HOME_GDBSTARTUP.  HOME_GDBSTARTUP could be returned as an empty
+   string if there is not startup file found.  */
+
+static void
+get_startup_files (std::string *home_gdbstartup)
+{
+  /* Cache the file lookup object so we only actually search for the files
+     once.  */
+  static std::unique_ptr<gdb_initfile_finder> init_files;
+  if (init_files == nullptr)
+    init_files = std::unique_ptr<gdb_initfile_finder>
+      (new gdb_initfile_finder (GDBSTARTUP,
+				nullptr, false, nullptr, false, false));
+
+  *home_gdbstartup = init_files->home_file ();
+}
+
 /* Start up the event loop.  This is the entry point to the event loop
    from the command loop.  */
 
@@ -563,7 +581,13 @@ enum cmdarg_kind
   CMDARG_INIT_FILE,
     
   /* Option type -iex.  */
-  CMDARG_INIT_COMMAND
+  CMDARG_INIT_COMMAND,
+
+  /* Option type -sx.  */
+  CMDARG_STARTUP_FILE,
+
+  /* Option type -sex.  */
+  CMDARG_STARTUP_COMMAND
 };
 
 /* Arguments of --command option and its counterpart.  */
@@ -741,6 +765,8 @@ captured_main_1 (struct captured_main_args *context)
       OPT_WINDOWS,
       OPT_IX,
       OPT_IEX,
+      OPT_SX,
+      OPT_SEX,
       OPT_READNOW,
       OPT_READNEVER
     };
@@ -790,6 +816,10 @@ captured_main_1 (struct captured_main_args *context)
       {"init-eval-command", required_argument, 0, OPT_IEX},
       {"ix", required_argument, 0, OPT_IX},
       {"iex", required_argument, 0, OPT_IEX},
+      {"startup-command", required_argument, 0, OPT_SX},
+      {"startup-eval-command", required_argument, 0, OPT_SEX},
+      {"sx", required_argument, 0, OPT_SX},
+      {"sex", required_argument, 0, OPT_SEX},
 #ifdef GDBTK
       {"tclcommand", required_argument, 0, 'z'},
       {"enable-external-editor", no_argument, 0, 'y'},
@@ -902,6 +932,12 @@ captured_main_1 (struct captured_main_args *context)
 	  case OPT_IEX:
 	    cmdarg_vec.emplace_back (CMDARG_INIT_COMMAND, optarg);
 	    break;
+	  case OPT_SX:
+	    cmdarg_vec.emplace_back (CMDARG_STARTUP_FILE, optarg);
+	    break;
+	  case OPT_SEX:
+	    cmdarg_vec.emplace_back (CMDARG_STARTUP_COMMAND, optarg);
+	    break;
 	  case 'B':
 	    batch_flag = batch_silent = 1;
 	    gdb_stdout = new null_file ();
@@ -1010,6 +1046,18 @@ captured_main_1 (struct captured_main_args *context)
   /* Initialize all files.  */
   gdb_init (gdb_program_name);
 
+  /* Process startup files and startup options from the command line.  */
+  if (!inhibit_gdbinit)
+    {
+      std::string home_gdbstartup;
+      get_startup_files (&home_gdbstartup);
+      if (!home_gdbstartup.empty () && !inhibit_home_gdbinit)
+	ret = catch_command_errors (source_script,
+				    home_gdbstartup.c_str (), 0);
+    }
+  execute_cmdargs (&cmdarg_vec, CMDARG_STARTUP_FILE,
+		   CMDARG_STARTUP_COMMAND, &ret);
+
   /* Now that gdb_init has created the initial inferior, we're in
      position to set args for that inferior.  */
   if (set_args)
@@ -1337,8 +1385,10 @@ print_gdb_help (struct ui_file *stream)
   std::vector<std::string> system_gdbinit;
   std::string home_gdbinit;
   std::string local_gdbinit;
+  std::string home_gdbstartup;
 
   get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
+  get_startup_files (&home_gdbstartup);
 
   /* Note: The options in the list below are only approximately sorted
      in the alphabetical order, so as to group closely related options
@@ -1412,6 +1462,16 @@ Other options:\n\n\
 		     Set GDB's data-directory to DIR.\n\
 "), stream);
   fputs_unfiltered (_("\n\
+At startup, GDB reads the following startup files and executes their commands:\n\
+"), stream);
+  if (!home_gdbstartup.empty ())
+    fprintf_unfiltered (stream, _("\
+   * user-specific startup file: %s\n\
+"), home_gdbstartup.c_str ());
+  if (home_gdbstartup.empty ())
+    fprintf_unfiltered (stream, _("\
+   None found.\n"));
+  fputs_unfiltered (_("\n\
 At startup, GDB reads the following init files and executes their commands:\n\
 "), stream);
   if (!system_gdbinit.empty ())
diff --git a/gdb/testsuite/gdb.base/startup-file.c b/gdb/testsuite/gdb.base/startup-file.c
new file mode 100644
index 00000000000..9811b15f06d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/startup-file.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/startup-file.exp b/gdb/testsuite/gdb.base/startup-file.exp
new file mode 100644
index 00000000000..e871a193ffa
--- /dev/null
+++ b/gdb/testsuite/gdb.base/startup-file.exp
@@ -0,0 +1,110 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test GDB's startup file mechanism.
+
+standard_testfile
+
+# Compile the test executable.
+if {[build_executable "failed to build" $testfile $srcfile]} {
+    return -1
+}
+
+# Start gdb and ensure that the initial version string is styled in
+# STYLE, use MESSAGE as the name of the test.
+proc check_gdb_startup_version_string { style { message "" } } {
+    if { $message == "" } {
+	set message "check startup version string has style $style"
+    }
+
+    gdb_exit
+    gdb_spawn
+    set vers [style "GNU gdb.*" $style]
+    gdb_test "" "^${vers}.*" $message
+}
+
+# Return a list containing two directory paths for newly created home
+# directories.
+#
+# The first directory is a HOME style home directory, it contains a
+# .gdbstartup file containing CONTENT.
+#
+# The second directory is an XDG_CONFIG_HOME style home directory, it
+# contains a sub-directory gdb/, inside which is a file gdbstartup
+# that also contains CONTENT.
+#
+# The PREFIX is used in both directory names and should be unique for
+# each call to this function.
+proc setup_home_directories { prefix content } {
+    set home_dir [standard_output_file "${prefix}-home"]
+    set xdg_home_dir [standard_output_file "${prefix}-xdg"]
+
+    file mkdir $home_dir
+    file mkdir "$xdg_home_dir/gdb"
+
+    # Write the content into the HOME directory.
+    set fd [open "$home_dir/.gdbstartup" w]
+    puts $fd $content
+    close $fd
+
+    # Copy this from the HOME directory into the XDG_CONFIG_HOME
+    # directory.
+    file copy -force "$home_dir/.gdbstartup" "$xdg_home_dir/gdb/gdbstartup"
+
+    return [list $home_dir $xdg_home_dir]
+}
+
+save_vars { env(TERM) } {
+    # We need an ANSI-capable terminal to get the output.
+    setenv TERM ansi
+
+    # Start GDB and confirm that the version string is styled.
+    check_gdb_startup_version_string version
+
+    # Create an empty directory we can use as HOME for some of the
+    # tests below.  When we set XDG_CONFIG_HOME we still need to point
+    # HOME at something otherwise GDB complains that it doesn't know
+    # where to create the index cache.
+    set empty_home_dir [standard_output_file fake-empty-home]
+
+    # Create two directories to use for the style setting test.
+    set dirs [setup_home_directories "style" \
+		  [multi_line_input \
+		       "set style version foreground none" \
+		       "set style version background none" \
+		       "set style version intensity normal"]]
+    set home_dir [lindex $dirs 0]
+    set xdg_home_dir [lindex $dirs 1]
+
+    # Now arrange to use the fake home directory startup file.
+    save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+	set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+	# Now test GDB when using the HOME directory.
+	set env(HOME) $home_dir
+	unset -nocomplain env(XDG_CONFIG_HOME)
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using HOME"
+
+	# Now test using the XDG_CONFIG_HOME folder.  We still need to
+	# have a HOME directory set otherwise GDB will issue an error
+	# about not knowing where to place the index cache.
+	set env(XDG_CONFIG_HOME) $xdg_home_dir
+	set env(HOME) $empty_home_dir
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using XDG_CONFIG_HOME"
+    }
+}
+
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index ad7d2884aae..cec157196b3 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -56,6 +56,7 @@ proc style {str style} {
 	address { set style 34 }
 	metadata { set style 2 }
 	version { set style "35;1" }
+	none { return $str }
     }
     return "\033\\\[${style}m${str}\033\\\[m"
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv2 3/3] gdb: add "set startup-quietly" command
  2021-01-26  9:48 [PATCHv2 0/3] Adding startup files to GDB Andrew Burgess
  2021-01-26  9:48 ` [PATCHv2 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
  2021-01-26  9:48 ` [PATCHv2 2/3] gdb: process startup files and startup command line options Andrew Burgess
@ 2021-01-26  9:48 ` Andrew Burgess
  2021-01-26 15:12   ` Eli Zaretskii
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  3 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-01-26  9:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

From: Tom Tromey <tom@tromey.com>

This adds a new command to change GDB to behave as though "-quiet"
were always given.  This new command can be added to the gdbstartup
file to affect future GDB sessions.

gdb/ChangeLog:

	* NEWS: Add entry.
	* main.c (captured_main_1): Call check_quiet_mode.
	* top.c (startup_quiet): New global.
	(check_quiet_mode): New function.
	(show_startup_quiet): New function.
	(init_main): Register new command.
	* top.h (check_quiet_mode): Declare.

gdb/doc/ChangeLog:

	* gdb.texinfo (Mode Options): Mention "set startup-quietly".

gdb/testsuite/ChangeLog:

	* gdb.base/startup-file.exp: Add more tests.
---
 gdb/ChangeLog                           | 11 +++++++
 gdb/NEWS                                |  6 ++++
 gdb/doc/ChangeLog                       |  5 ++++
 gdb/doc/gdb.texinfo                     |  9 ++++++
 gdb/main.c                              |  5 ++++
 gdb/testsuite/ChangeLog                 |  4 +++
 gdb/testsuite/gdb.base/startup-file.exp | 39 +++++++++++++++++++++++++
 gdb/top.c                               | 33 +++++++++++++++++++++
 gdb/top.h                               |  5 ++++
 9 files changed, 117 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index 368cab5fec6..2bd2ec7e975 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -92,6 +92,12 @@ set style version background COLOR
 set style version intensity VALUE
   Control the styling of GDB's version number text.
 
+set startup-quietly on|off
+show startup-quietly
+  When enabled, this causes GDB to act as if "-silent" were always
+  passed on the command line.  This command needs to be added to a
+  gdbstartup file in order to affect GDB.
+
 *** Changes in GDB 10
 
 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 09f64302ba6..224cc9ae85a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1114,6 +1114,15 @@
 ``Quiet''.  Do not print the introductory and copyright messages.  These
 messages are also suppressed in batch mode.
 
+@kindex set startup-quietly
+@kindex show startup-quietly
+This can also be enabled using @code{set startup-quietly on}.  The
+default is @code{off}.  Use @code{show startup-quietly} to see the
+current setting.  Changing this setting will have no affect on the
+current @value{GDBN} session.  Add @code{set startup-quietly on} to
+the startup command file (@pxref{Initialization Files,,Initialization
+Files}) to affect future @value{GDBN} sessions.
+
 @item -batch
 @cindex @code{--batch}
 Run in batch mode.  Exit with status @code{0} after processing all the
diff --git a/gdb/main.c b/gdb/main.c
index fe1ca27c255..1f863d191bc 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -1058,6 +1058,11 @@ captured_main_1 (struct captured_main_args *context)
   execute_cmdargs (&cmdarg_vec, CMDARG_STARTUP_FILE,
 		   CMDARG_STARTUP_COMMAND, &ret);
 
+  /* 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.  */
   if (set_args)
diff --git a/gdb/testsuite/gdb.base/startup-file.exp b/gdb/testsuite/gdb.base/startup-file.exp
index e871a193ffa..d3f46c7e4c4 100644
--- a/gdb/testsuite/gdb.base/startup-file.exp
+++ b/gdb/testsuite/gdb.base/startup-file.exp
@@ -66,6 +66,21 @@ proc setup_home_directories { prefix content } {
     return [list $home_dir $xdg_home_dir]
 }
 
+# Restart GDB and ensure that there's no license text, we should just
+# drop straight to the prompt.
+proc check_gdb_startups_up_quietly { message } {
+    global gdb_prompt
+
+    gdb_exit
+    gdb_spawn
+
+    gdb_test_multiple "" $message {
+	-re "^$gdb_prompt $" {
+	    pass $gdb_test_name
+	}
+    }
+}
+
 save_vars { env(TERM) } {
     # We need an ANSI-capable terminal to get the output.
     setenv TERM ansi
@@ -106,5 +121,29 @@ save_vars { env(TERM) } {
 	check_gdb_startup_version_string none \
 	    "check version string is unstyled using XDG_CONFIG_HOME"
     }
+
+    # Create two directories to use for the quiet startup test.
+    set dirs [setup_home_directories "quiet" "set startup-quietly on"]
+    set home_dir [lindex $dirs 0]
+    set xdg_home_dir [lindex $dirs 1]
+
+    # Now arrange to use the fake home directory startup file.
+    save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+	set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+	# Now test GDB when using the HOME directory.
+	set env(HOME) $home_dir
+	unset -nocomplain env(XDG_CONFIG_HOME)
+	check_gdb_startups_up_quietly \
+	    "check GDB starts quietly using HOME"
+
+	# Now test using the XDG_CONFIG_HOME folder.  We still need to
+	# have a HOME directory set otherwise GDB will issue an error
+	# about not knowing where to place the index cache.
+	set env(XDG_CONFIG_HOME) $xdg_home_dir
+	set env(HOME) $empty_home_dir
+	check_gdb_startups_up_quietly \
+	    "check GDB starts quietly using XDG_CONFIG_HOME"
+    }
 }
 
diff --git a/gdb/top.c b/gdb/top.c
index 08c47422514..5d3c951b8a2 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -2146,6 +2146,28 @@ set_history_filename (const char *args,
     }
 }
 
+/* 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)
 {
@@ -2300,6 +2322,17 @@ input settings."),
 			show_interactive_mode,
 			&setlist, &showlist);
 
+  c = 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 .gdbstartup 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\
diff --git a/gdb/top.h b/gdb/top.h
index f58bebbb385..9438e52331b 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -291,4 +291,9 @@ extern char *handle_line_of_input (struct buffer *cmd_line_buffer,
 				   const char *rl, int repeat,
 				   const char *annotation_suffix);
 
+/* Call at startup to see if the user has requested that gdb start up
+   quietly.  */
+
+extern bool check_quiet_mode ();
+
 #endif
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 1/3] gdb: refactor the initialization file lookup code
  2021-01-26  9:48 ` [PATCHv2 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
@ 2021-01-26 15:09   ` Simon Marchi
  0 siblings, 0 replies; 20+ messages in thread
From: Simon Marchi @ 2021-01-26 15:09 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches

On 2021-01-26 4:48 a.m., Andrew Burgess wrote:
> +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 std::unique_ptr<gdb_initfile_finder> init_files;
> +  if (init_files == nullptr)
> +    init_files = std::unique_ptr<gdb_initfile_finder>
> +      (new gdb_initfile_finder (GDBINIT,

Just a nit, but I'd use an optional instead of a unique_ptr here, just
because we don't need dynamic allocation.

Otherwise, LGTM.

Simon

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 3/3] gdb: add "set startup-quietly" command
  2021-01-26  9:48 ` [PATCHv2 3/3] gdb: add "set startup-quietly" command Andrew Burgess
@ 2021-01-26 15:12   ` Eli Zaretskii
  0 siblings, 0 replies; 20+ messages in thread
From: Eli Zaretskii @ 2021-01-26 15:12 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, tom

> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Tue, 26 Jan 2021 09:48:13 +0000
> Cc: Tom Tromey <tom@tromey.com>
> 
> From: Tom Tromey <tom@tromey.com>
> 
> This adds a new command to change GDB to behave as though "-quiet"
> were always given.  This new command can be added to the gdbstartup
> file to affect future GDB sessions.
> 
> gdb/ChangeLog:
> 
> 	* NEWS: Add entry.
> 	* main.c (captured_main_1): Call check_quiet_mode.
> 	* top.c (startup_quiet): New global.
> 	(check_quiet_mode): New function.
> 	(show_startup_quiet): New function.
> 	(init_main): Register new command.
> 	* top.h (check_quiet_mode): Declare.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Mode Options): Mention "set startup-quietly".
> 
> gdb/testsuite/ChangeLog:
> 
> 	* gdb.base/startup-file.exp: Add more tests.

Thanks.

> +set startup-quietly on|off
> +show startup-quietly
> +  When enabled, this causes GDB to act as if "-silent" were always
> +  passed on the command line.  This command needs to be added to a
> +  gdbstartup file in order to affect GDB.

What is "gdbstartup file"?

Also, the manual seems to describe the use of this feature
differently:

> +@kindex set startup-quietly
> +@kindex show startup-quietly
> +This can also be enabled using @code{set startup-quietly on}.  The
> +default is @code{off}.  Use @code{show startup-quietly} to see the
> +current setting.  Changing this setting will have no affect on the
> +current @value{GDBN} session.  Add @code{set startup-quietly on} to
> +the startup command file (@pxref{Initialization Files,,Initialization
> +Files}) to affect future @value{GDBN} sessions.

Why is there a difference between the two descriptions?

Also, the sentence starting with "Changing this setting will have" is
slightly confusing, because it is not absolutely clear that it refers
only to the "set" command issued from the CLI, and does NOT affect the
startup file setting.  Could you please clarify this text?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 2/3] gdb: process startup files and startup command line options
  2021-01-26  9:48 ` [PATCHv2 2/3] gdb: process startup files and startup command line options Andrew Burgess
@ 2021-01-26 15:22   ` Eli Zaretskii
  2021-01-26 15:32     ` Simon Marchi
  2021-01-26 15:30   ` Simon Marchi
  1 sibling, 1 reply; 20+ messages in thread
From: Eli Zaretskii @ 2021-01-26 15:22 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Tue, 26 Jan 2021 09:48:12 +0000
> 
> Adds the ability to process commands at a new phase during GDB's
> startup.  This phase is earlier than the current initialisation file
> processing, before GDB has produced any output.

Thanks.

> +* GDB will now load and process commands from ~/.config/gdb/gdbstartup
> +  or ~/.gdbstartup if these files are present.  These files are
> +  processed earlier than any of the previous initialization files and
> +  can affect parts of GDB's startup that previously had already been
> +  completed before the initialization files were read, for example
> +  styling of the initial GDB greeting.
> +
> +* GDB now has two new options "--startup-command" and
> +  "--startup-eval-command" with corresponding short options "-sx" and
> +  "-sex" that allow options (that would normally appear in a
> +  gdbstartup file) to be passed on the command line.

This part is OK.

> +@item -startup-command @var{file}
> +@itemx -sx @var{file}
> +@cindex @code{--startup-command}
> +@cindex @code{-sx}
> +Execute commands from file @var{file} as early as possible during the
> +initialization process, before any output is produced.
> +@xref{Startup}.
> +
> +@item -startup-eval-command @var{command}
> +@itemx -sex @var{command}
> +@cindex @code{--startup-eval-command}
> +@cindex @code{-sex}
> +Execute a single @value{GDBN} command as early as possible during the
> +initialization process, before any output is produced.

"As early as possible" could be taken as meaning there's something
non-deterministic in choosing the stage where these commands are
executed.  How about "very early in the initialization process"
instead?

> +The files processed are split into two categories @dfn{startup files}
> +and @dfn{initialization files}.
> +
> +The startup file is loaded as early as possible during

The first sentence above says "files", the second says "the file", as
if there's only one.  Which one is it?

(And the same issue with "as early as possible" as before.)

> +@value{GDBN}'s startup, before the interpreter (@pxref{Interpreters})
> +has been initialised, and before the default target (@pxref{Targets}
> +is initialised.  Only @code{set} or @code{source} commands should be

Our convention is to use the US English spellings, so please use
"initialized".

> +restrictions.  Only commands that can appear in a startup file shold
                                                                  ^^^^^
A typo there.

> +While on Apple hosts the locations searched are:

Such a sentence shouldn't start with "while".  I suggest "By
contrast," instead.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 2/3] gdb: process startup files and startup command line options
  2021-01-26  9:48 ` [PATCHv2 2/3] gdb: process startup files and startup command line options Andrew Burgess
  2021-01-26 15:22   ` Eli Zaretskii
@ 2021-01-26 15:30   ` Simon Marchi
  1 sibling, 0 replies; 20+ messages in thread
From: Simon Marchi @ 2021-01-26 15:30 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches

On 2021-01-26 4:48 a.m., Andrew Burgess wrote:> Adds the ability to process commands at a new phase during GDB's
> startup.  This phase is earlier than the current initialisation file
> processing, before GDB has produced any output.
> 
> The number of commands that can be processed at this early stage will
> be limited, and it is expected that the only commands that would be
> processed at this stage will relate to some of the fundamentals of how
> GDB starts up.
> 
> Currently the only commands that it makes sense to add to this startup
> file are those like 'set style version ....' as the version string is
> displayed during startup before the standard initialization files are
> parsed.  As such this commit fully resolved bug cli/25956.
> 
> This commit adds a mechanism to find these startup files as well as
> some corresponding command line flags.
> 
> The startup files that GDB will currently check for are
> ~/.config/gdb/gdbstartup (on Linux like systems) or ~/.gdbstartup if
> the former is not found.
> 
> The output of 'gdb --help' has been extended to include a list of the
> startup files being processed.

Functionally, that all LGTM.

Sorry if I'm late to the game, but I have to admit that I find the name
a bit confusing.  If I didn't already know which is which, I couldn't
tell which of "init" and "startup" happens earlier than the other.
"init" and "earlyinit" would be unambiguous, for example.  But this is a
minor detail, feel free to ignore.  The documentation still makes it
clear.

Simon

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 2/3] gdb: process startup files and startup command line options
  2021-01-26 15:22   ` Eli Zaretskii
@ 2021-01-26 15:32     ` Simon Marchi
  0 siblings, 0 replies; 20+ messages in thread
From: Simon Marchi @ 2021-01-26 15:32 UTC (permalink / raw)
  To: Eli Zaretskii, Andrew Burgess; +Cc: gdb-patches

On 2021-01-26 10:22 a.m., Eli Zaretskii via Gdb-patches wrote:>> +While on Apple hosts the locations searched are:
> 
> Such a sentence shouldn't start with "while".  I suggest "By
> contrast," instead.

I would also add: I think we should use actual operating system's name,
as "Apple" isn't an operating system.  That would be "macOS".  But it
probably needs to be changed across the manual, as that name is quite
recent (it used to be "Mac OS X").

Simon


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv3 0/3] Adding startup files to GDB
  2021-01-26  9:48 [PATCHv2 0/3] Adding startup files to GDB Andrew Burgess
                   ` (2 preceding siblings ...)
  2021-01-26  9:48 ` [PATCHv2 3/3] gdb: add "set startup-quietly" command Andrew Burgess
@ 2021-02-18 16:41 ` Andrew Burgess
  2021-02-18 16:41   ` [PATCHv3 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
                     ` (3 more replies)
  3 siblings, 4 replies; 20+ messages in thread
From: Andrew Burgess @ 2021-02-18 16:41 UTC (permalink / raw)
  To: gdb-patches

Changes since v2:

Patch #1

 - Make use of gdb::optional as Simon suggested.

Patch #2

 - Rename 'startup' files to 'earlyinit' files as Simon suggested.

 - Extensive documentation changes to address Eli's feedback, and to
   reflect the naming change.

 - Renamed the test script to reflect the naming change.

Patch #3

 - Updates to the documentation to (I hope) address Eli's feedback.


Thanks,
Andrew

---

Andrew Burgess (2):
  gdb: refactor the initialization file lookup code
  gdb: process early initialization files and command line options

Tom Tromey (1):
  gdb: add "set startup-quietly" command

 gdb/ChangeLog                              |  33 +++
 gdb/NEWS                                   |  19 ++
 gdb/config.in                              |   3 +
 gdb/configure                              |   6 +
 gdb/configure.ac                           |   3 +
 gdb/doc/ChangeLog                          |  14 ++
 gdb/doc/gdb.texinfo                        | 125 +++++++++-
 gdb/main.c                                 | 253 +++++++++++++++------
 gdb/testsuite/ChangeLog                    |  11 +
 gdb/testsuite/gdb.base/early-init-file.c   |  22 ++
 gdb/testsuite/gdb.base/early-init-file.exp | 149 ++++++++++++
 gdb/testsuite/lib/gdb-utils.exp            |   1 +
 gdb/top.c                                  |  33 +++
 gdb/top.h                                  |   5 +
 14 files changed, 603 insertions(+), 74 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/early-init-file.c
 create mode 100644 gdb/testsuite/gdb.base/early-init-file.exp

-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv3 1/3] gdb: refactor the initialization file lookup code
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
@ 2021-02-18 16:41   ` Andrew Burgess
  2021-02-18 16:41   ` [PATCHv3 2/3] gdb: process early initialization files and command line options Andrew Burgess
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Andrew Burgess @ 2021-02-18 16:41 UTC (permalink / raw)
  To: gdb-patches

In preparation for the next patch, which adds startup files, this
commit refactors the code for looking up the initialization files so
that the code can be more easily reused in the next commit.

There should be no user visible changes after this commit.

gdb/ChangeLog:

	* main.c (relocate_gdbinit_path_maybe_in_datadir): Rename to...
	(relocate_file_path_maybe_in_datadir): ...this.
	(class gdb_initfile_finder): New class.
	(get_init_files): Now uses gdb_initfile_finder.
	(print_gdb_help): Print 'None found' when there are no init files.
---
 gdb/ChangeLog |   8 +++
 gdb/main.c    | 187 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 132 insertions(+), 63 deletions(-)

diff --git a/gdb/main.c b/gdb/main.c
index 46b71f5aafd..2ba39273d07 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -203,8 +203,8 @@ relocate_gdb_directory (const char *initial, bool relocatable)
    otherwise.  */
 
 static std::string
-relocate_gdbinit_path_maybe_in_datadir (const std::string &file,
-					bool relocatable)
+relocate_file_path_maybe_in_datadir (const std::string &file,
+				     bool relocatable)
 {
   size_t datadir_len = strlen (GDB_DATADIR);
 
@@ -233,45 +233,52 @@ relocate_gdbinit_path_maybe_in_datadir (const std::string &file,
     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::vector<std::string> *system_gdbinit,
-		std::string *home_gdbinit,
-		std::string *local_gdbinit)
+/* 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.  */
+
+class gdb_initfile_finder
 {
-  static std::vector<std::string> sysgdbinit;
-  static std::string homeinit;
-  static std::string localinit;
-  static int initialized = 0;
+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 (!initialized)
-    {
-      struct stat homebuf, cwdbuf, s;
+    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);
+      }
 
-      if (SYSTEM_GDBINIT[0])
-	{
-	  std::string relocated_sysgdbinit
-	    = relocate_gdbinit_path_maybe_in_datadir
-		(SYSTEM_GDBINIT, SYSTEM_GDBINIT_RELOCATABLE);
-	  if (!relocated_sysgdbinit.empty ()
-	      && stat (relocated_sysgdbinit.c_str (), &s) == 0)
-	    sysgdbinit.push_back (relocated_sysgdbinit);
-	}
-      if (SYSTEM_GDBINIT_DIR[0])
-	{
-	  std::string relocated_gdbinit_dir
-	    = relocate_gdbinit_path_maybe_in_datadir
-		(SYSTEM_GDBINIT_DIR, SYSTEM_GDBINIT_DIR_RELOCATABLE);
-	  if (!relocated_gdbinit_dir.empty ()) {
-	    gdb_dir_up dir (opendir (relocated_gdbinit_dir.c_str ()));
+    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;
-		for (;;)
+		while (true)
 		  {
 		    struct dirent *ent = readdir (dir.get ());
 		    if (ent == nullptr)
@@ -279,28 +286,28 @@ get_init_files (std::vector<std::string> *system_gdbinit,
 		    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 filename
-		      = relocated_gdbinit_dir + SLASH_STRING + name;
-		    if (stat (filename.c_str (), &s) != 0
+		    /* 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 (filename.c_str ());
+		      = 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.  */
+		       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 (filename));
+		      files.push_back (std::move (tmp_filename));
 		  }
 		std::sort (files.begin (), files.end ());
-		sysgdbinit.insert (sysgdbinit.end (),
-				   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
@@ -308,25 +315,75 @@ get_init_files (std::vector<std::string> *system_gdbinit,
 	 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));
 
-      homeinit = find_gdb_home_config_file (GDBINIT, &homebuf);
+    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;
-	}
+    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;
+      }
+  }
 
-      initialized = 1;
-    }
+  DISABLE_COPY_AND_ASSIGN (gdb_initfile_finder);
+
+  /* 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;
 
-  *system_gdbinit = sysgdbinit;
-  *home_gdbinit = homeinit;
-  *local_gdbinit = localinit;
+  /* 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 ();
 }
 
 /* Start up the event loop.  This is the entry point to the event loop
@@ -1375,6 +1432,10 @@ At startup, GDB reads the following init files and executes their commands:\n\
     fprintf_unfiltered (stream, _("\
    * local init file (see also 'set auto-load local-gdbinit'): ./%s\n\
 "), local_gdbinit.c_str ());
+  if (system_gdbinit.empty () && home_gdbinit.empty ()
+      && local_gdbinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   None found.\n"));
   fputs_unfiltered (_("\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\
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv3 2/3] gdb: process early initialization files and command line options
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  2021-02-18 16:41   ` [PATCHv3 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
@ 2021-02-18 16:41   ` Andrew Burgess
  2021-02-18 17:46     ` Eli Zaretskii
  2021-02-18 16:41   ` [PATCHv3 3/3] gdb: add "set startup-quietly" command Andrew Burgess
  2021-03-31 20:11   ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  3 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-02-18 16:41 UTC (permalink / raw)
  To: gdb-patches

Adds the ability to process commands at a new phase during GDB's
startup.  This phase is earlier than the current initialisation file
processing, before GDB has produced any output.

The number of commands that can be processed at this early stage will
be limited, and it is expected that the only commands that would be
processed at this stage will relate to some of the fundamentals of how
GDB starts up.

Currently the only commands that it makes sense to add to this early
initialization file are those like 'set style version ....' as the
version string is displayed during startup before the standard
initialization files are parsed.  As such this commit fully resolved
bug cli/25956.

This commit adds a mechanism to execute these early initialization
files from a users HOME directory, as well as some corresponding
command line flags for GDB.

The early initialization files that GDB will currently check for are
~/.config/gdb/gdbstartup (on Linux like systems) or ~/.gdbstartup if
the former is not found.

The output of 'gdb --help' has been extended to include a list of the
early initialization files being processed.

gdb/ChangeLog:

	PR cli/25956
	* NEWS: Mention new early init files and command line options.
	* config.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: Define GDBEARLYINIT.
	* main.c (get_earlyinit_files): New function.
	(enum cmdarg_kind): Add CMDARG_EARLYINIT_FILE and
	CMDARG_EARLYINIT_COMMAND.
	(captured_main_1): Add support for new command line flags, and for
	processing startup files.
	(print_gdb_help): Include startup files in the output.
<
gdb/doc/ChangeLog:

	PR cli/25956
	* gdb.texinfo (File Options): Mention new command line options.
	(Startup): Discuss when early init files are processed.
	(Initialization Files): Add description of early init files.
	(Output Styling): Update description of 'version' style.
	(gdb man): Mention early init files.

gdb/testsuite/ChangeLog:

	PR cli/25956
	* gdb.base/early-init-file.c: New file.
	* gdb.base/early-init-file.exp: New file.
	* lib/gdb-utils.exp (style): Handle style 'none'.
---
 gdb/ChangeLog                              |  14 +++
 gdb/NEWS                                   |  12 +++
 gdb/config.in                              |   3 +
 gdb/configure                              |   6 ++
 gdb/configure.ac                           |   3 +
 gdb/doc/ChangeLog                          |   9 ++
 gdb/doc/gdb.texinfo                        | 117 +++++++++++++++++++--
 gdb/main.c                                 |  61 ++++++++++-
 gdb/testsuite/ChangeLog                    |   7 ++
 gdb/testsuite/gdb.base/early-init-file.c   |  22 ++++
 gdb/testsuite/gdb.base/early-init-file.exp | 110 +++++++++++++++++++
 gdb/testsuite/lib/gdb-utils.exp            |   1 +
 12 files changed, 354 insertions(+), 11 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/early-init-file.c
 create mode 100644 gdb/testsuite/gdb.base/early-init-file.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 1dfbbc648eb..fdd526e86cf 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -33,6 +33,18 @@
   the use of the GNAT encoding (based on information added to the type's
   name following a GNAT-specific format).
 
+* GDB will now load and process commands from ~/.config/gdb/gdbearlyinit
+  or ~/.gdbearlyinit if these files are present.  These files are
+  processed earlier than any of the previous initialization files and
+  can affect parts of GDB's startup that previously had already been
+  completed before the initialization files were read, for example
+  styling of the initial GDB greeting.
+
+* GDB now has two new options "--early-init-command" and
+  "--early-init-eval-command" with corresponding short options "-eix"
+  and "-eiex" that allow options (that would normally appear in a
+  gdbearlyinit file) to be passed on the command line.
+
 * New commands
 
 set debug event-loop
diff --git a/gdb/config.in b/gdb/config.in
index 14a77c661d5..db860c7cea0 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -43,6 +43,9 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* The .gdbearlyinit filename. */
+#undef GDBEARLYINIT
+
 /* The .gdbinit filename. */
 #undef GDBINIT
 
diff --git a/gdb/configure b/gdb/configure
index 51b4d1921c5..ec8c9c413a1 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -16778,6 +16778,12 @@ _ACEOF
 
 
 
+cat >>confdefs.h <<_ACEOF
+#define GDBEARLYINIT ".gdbearlyinit"
+_ACEOF
+
+
+
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
 # except that the argument to --with-sysroot is optional.
 # --with-sysroot (or --with-sysroot=yes) sets the default sysroot path.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 618c59166e4..edd7d2915ff 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1819,6 +1819,9 @@ case $host_os in
 esac
 AC_DEFINE_UNQUOTED(GDBINIT,"$gdbinit",[The .gdbinit filename.])
 
+dnl Set the host's .gdbstartup filename
+AC_DEFINE_UNQUOTED(GDBEARLYINIT,".gdbearlyinit",[The .gdbearlyinit filename.])
+
 dnl Handle optional features that can be enabled.
 
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 90f0c7683f6..b900d777c13 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1040,6 +1040,20 @@
 after loading gdbinit files).
 @xref{Startup}.
 
+@item -early-init-command @var{file}
+@itemx -eix @var{file}
+@cindex @code{--early-init-command}
+@cindex @code{-eix}
+Execute commands from file @var{file} very early in the initialization
+process, before any output is produced.  @xref{Startup}.
+
+@item -early-init-eval-command @var{command}
+@itemx -eiex @var{command}
+@cindex @code{--early-init-eval-command}
+@cindex @code{-eiex}
+Execute a single @value{GDBN} command very early in the initialization
+process, before any output is produced.  @xref{Startup}.
+
 @item -directory @var{directory}
 @itemx -d @var{directory}
 @cindex @code{--directory}
@@ -1291,6 +1305,22 @@
 Here's the description of what @value{GDBN} does during session startup:
 
 @enumerate
+
+@item
+Performs minimal setup required to initialise basic internal state.
+
+@item
+@cindex early initialization file
+Read commands from the early initialization file (if any) in your home
+directory.  Only a restricted set of commands can be placed into an
+early initialization file, @pxref{Initialization Files} for details.
+
+@item
+Executes commands and command files specified by the @samp{-eiex} and
+@samp{-eix} command line options in their specified order.  Only a
+restricted set of commands can be used with @samp{-eiex} and
+@samp{eix}, @pxref{Initialization Files} for details.
+
 @item
 Sets up the command interpreter as specified by the command line
 (@pxref{Mode Options, interpreter}).
@@ -1367,13 +1397,79 @@
 startup, in the order they will be loaded, you can use @kbd{gdb
 --help}.
 
+The @dfn{early initialization} file is loaded very early in
+@value{GDBN}'s initialization process, before the interpreter
+(@pxref{Interpreters}) has been initialized, and before the default
+target (@pxref{Targets} is initialized.  Only @code{set} or
+@code{source} commands should be placed into an early initialization
+file, and the only @code{set} commands that can be used are those that
+control how @value{GDBN} starts up.
+
+Commands that can be placed into an early initialization file will be
+documented as such throughout this manual.  Any command that is not
+documented as being suitable for an early initialization file should
+instead be placed into a general initialization file.  Command files
+passed to @code{--early-init-command} or @code{-eix} are also early
+initialization files, with the same command restrictions.  Only
+commands that can appear in an early initialization file should be
+passed to @code{--early-init-eval-command} or @code{-eiex}.
+
+In contrast, the @dfn{general initialization} files are processed
+later, after @value{GDBN} has finished its own internal initialization
+process, any valid command can be used in these files.
+
+Throughout the rest of this document the term @dfn{initialization
+file} refers to one of the general initialization files, not the early
+initialization file.  Any discussion of the early initialization file
+will specifically mention that it is the early initialization file
+being discussed.
+
 As the system wide and home directory initialization files are
 processed before most command line options, changes to settings
 (e.g. @samp{set complaints}) can affect subsequent processing of
 command line options and operands.
 
-The following sections describe where @value{GDBN} looks for the
-initialization and the order that the files are searched for.
+The following sections describe where @value{GDBN} looks for the early
+initialization and initialization files, and the order that the files
+are searched for.
+
+@subsubsection Home directory early initialization files
+
+@value{GDBN} initially looks for an early initialization file in the
+users home directory@footnote{On DOS/Windows systems, the home
+directory is the one pointed to by the @code{HOME} environment
+variable.}.  There are a number of locations that @value{GDBN} will
+search in the home directory, these locations are searched in order
+and @value{GDBN} will load the first file that it finds, and
+subsequent locations will not be checked.
+
+On non-macOS hosts the locations searched are:
+@itemize
+@item
+The file @file{gdb/gdbearlyinit} within the directory pointed to by the
+environment variable @env{XDG_CONFIG_HOME}, if it is defined.
+@item
+The file @file{.config/gdb/gdbearlyinit} within the directory pointed to
+by the environment variable @env{HOME}, if it is defined.
+@item
+The file @file{.gdbearlyinit} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+By contrast on macOS hosts the locations searched are:
+@itemize
+@item
+The file @file{Library/Preferences/gdb/gdbearlyinit} within the
+directory pointed to by the environment variable @env{HOME}, if it is
+defined.
+@item
+The file @file{.gdbearlyinit} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+It is possible to prevent the home directory early initialization file
+from being loaded using the @samp{-nx} or @samp{-nh} command line
+options, @pxref{Mode Options,,Choosing Modes}.
 
 @anchor{System Wide Init Files}
 @subsubsection System wide initialization files
@@ -25813,11 +25909,10 @@
 intensity.  The version number is displayed in two places, the output
 of @command{show version}, and when @value{GDBN} starts up.
 
-Currently the version string displayed at startup is printed before
-@value{GDBN} has parsed any command line options, or parsed any
-command files, so there is currently no way to control the styling of
-this string.  However, @value{GDBN}'s @code{--quiet} command line option
-can be used to disable printing of the version string on startup.
+In order to control how @value{GDBN} styles the version number at
+startup, add the @code{set style version} family of commands to the
+early initialization command file (@pxref{Initialization
+Files}).
 
 @item title
 Control the styling of titles.  These are managed with the
@@ -46622,12 +46717,14 @@
 Add @var{directory} to the path to search for source files.
 
 @item -nh
-Do not execute commands from @file{~/.config/gdb/gdbinit} or
-@file{~/.gdbinit}.
+Do not execute commands from @file{~/.config/gdb/gdbinit},
+@file{~/.gdbinit}, @file{~/.config/gdb/gdbearlyinit}, or
+@file{~/.gdbearlyinit}
 
 @item -nx
 @itemx -n
-Do not execute commands from any @file{.gdbinit} initialization files.
+Do not execute commands from any @file{.gdbinit} or
+@file{.gdbearlyinit} initialization files.
 
 @item -quiet
 @itemx -q
diff --git a/gdb/main.c b/gdb/main.c
index 2ba39273d07..5633381fdd5 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -386,6 +386,22 @@ get_init_files (std::vector<std::string> *system_gdbinit,
   *local_gdbinit = init_files->local_file ();
 }
 
+/* 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
+get_earlyinit_files (std::string *home_gdbearlyinit)
+{
+  /* 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 ();
+}
+
 /* Start up the event loop.  This is the entry point to the event loop
    from the command loop.  */
 
@@ -560,7 +576,13 @@ enum cmdarg_kind
   CMDARG_INIT_FILE,
     
   /* Option type -iex.  */
-  CMDARG_INIT_COMMAND
+  CMDARG_INIT_COMMAND,
+
+  /* Option type -sx.  */
+  CMDARG_EARLYINIT_FILE,
+
+  /* Option type -sex.  */
+  CMDARG_EARLYINIT_COMMAND
 };
 
 /* Arguments of --command option and its counterpart.  */
@@ -738,6 +760,8 @@ captured_main_1 (struct captured_main_args *context)
       OPT_WINDOWS,
       OPT_IX,
       OPT_IEX,
+      OPT_EIX,
+      OPT_EIEX,
       OPT_READNOW,
       OPT_READNEVER
     };
@@ -787,6 +811,10 @@ captured_main_1 (struct captured_main_args *context)
       {"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'},
@@ -899,6 +927,12 @@ captured_main_1 (struct captured_main_args *context)
 	  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 ();
@@ -1007,6 +1041,18 @@ captured_main_1 (struct captured_main_args *context)
   /* Initialize all files.  */
   gdb_init (gdb_program_name);
 
+  /* 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);
+
   /* Now that gdb_init has created the initial inferior, we're in
      position to set args for that inferior.  */
   if (set_args)
@@ -1334,8 +1380,10 @@ print_gdb_help (struct ui_file *stream)
   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
@@ -1409,6 +1457,17 @@ Other options:\n\n\
 		     Set GDB's data-directory to DIR.\n\
 "), stream);
   fputs_unfiltered (_("\n\
+At startup, GDB reads the following early init files and executes their\n\
+commands:\n\
+"), stream);
+  if (!home_gdbearlyinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   * user-specific early init file: %s\n\
+"), home_gdbearlyinit.c_str ());
+  if (home_gdbearlyinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   None found.\n"));
+  fputs_unfiltered (_("\n\
 At startup, GDB reads the following init files and executes their commands:\n\
 "), stream);
   if (!system_gdbinit.empty ())
diff --git a/gdb/testsuite/gdb.base/early-init-file.c b/gdb/testsuite/gdb.base/early-init-file.c
new file mode 100644
index 00000000000..9811b15f06d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/early-init-file.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/early-init-file.exp b/gdb/testsuite/gdb.base/early-init-file.exp
new file mode 100644
index 00000000000..116a3e83761
--- /dev/null
+++ b/gdb/testsuite/gdb.base/early-init-file.exp
@@ -0,0 +1,110 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test GDB's early init file mechanism.
+
+standard_testfile
+
+# Compile the test executable.
+if {[build_executable "failed to build" $testfile $srcfile]} {
+    return -1
+}
+
+# Start gdb and ensure that the initial version string is styled in
+# STYLE, use MESSAGE as the name of the test.
+proc check_gdb_startup_version_string { style { message "" } } {
+    if { $message == "" } {
+	set message "check startup version string has style $style"
+    }
+
+    gdb_exit
+    gdb_spawn
+    set vers [style "GNU gdb.*" $style]
+    gdb_test "" "^${vers}.*" $message
+}
+
+# Return a list containing two directory paths for newly created home
+# directories.
+#
+# The first directory is a HOME style home directory, it contains a
+# .gdbearlyinit file containing CONTENT.
+#
+# The second directory is an XDG_CONFIG_HOME style home directory, it
+# contains a sub-directory gdb/, inside which is a file gdbearlyinit
+# that also contains CONTENT.
+#
+# The PREFIX is used in both directory names and should be unique for
+# each call to this function.
+proc setup_home_directories { prefix content } {
+    set home_dir [standard_output_file "${prefix}-home"]
+    set xdg_home_dir [standard_output_file "${prefix}-xdg"]
+
+    file mkdir $home_dir
+    file mkdir "$xdg_home_dir/gdb"
+
+    # Write the content into the HOME directory.
+    set fd [open "$home_dir/.gdbearlyinit" w]
+    puts $fd $content
+    close $fd
+
+    # Copy this from the HOME directory into the XDG_CONFIG_HOME
+    # directory.
+    file copy -force "$home_dir/.gdbearlyinit" "$xdg_home_dir/gdb/gdbearlyinit"
+
+    return [list $home_dir $xdg_home_dir]
+}
+
+save_vars { env(TERM) } {
+    # We need an ANSI-capable terminal to get the output.
+    setenv TERM ansi
+
+    # Start GDB and confirm that the version string is styled.
+    check_gdb_startup_version_string version
+
+    # Create an empty directory we can use as HOME for some of the
+    # tests below.  When we set XDG_CONFIG_HOME we still need to point
+    # HOME at something otherwise GDB complains that it doesn't know
+    # where to create the index cache.
+    set empty_home_dir [standard_output_file fake-empty-home]
+
+    # Create two directories to use for the style setting test.
+    set dirs [setup_home_directories "style" \
+		  [multi_line_input \
+		       "set style version foreground none" \
+		       "set style version background none" \
+		       "set style version intensity normal"]]
+    set home_dir [lindex $dirs 0]
+    set xdg_home_dir [lindex $dirs 1]
+
+    # Now arrange to use the fake home directory early init file.
+    save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+	set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+	# Now test GDB when using the HOME directory.
+	set env(HOME) $home_dir
+	unset -nocomplain env(XDG_CONFIG_HOME)
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using HOME"
+
+	# Now test using the XDG_CONFIG_HOME folder.  We still need to
+	# have a HOME directory set otherwise GDB will issue an error
+	# about not knowing where to place the index cache.
+	set env(XDG_CONFIG_HOME) $xdg_home_dir
+	set env(HOME) $empty_home_dir
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using XDG_CONFIG_HOME"
+    }
+}
+
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index ad7d2884aae..cec157196b3 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -56,6 +56,7 @@ proc style {str style} {
 	address { set style 34 }
 	metadata { set style 2 }
 	version { set style "35;1" }
+	none { return $str }
     }
     return "\033\\\[${style}m${str}\033\\\[m"
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv3 3/3] gdb: add "set startup-quietly" command
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  2021-02-18 16:41   ` [PATCHv3 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
  2021-02-18 16:41   ` [PATCHv3 2/3] gdb: process early initialization files and command line options Andrew Burgess
@ 2021-02-18 16:41   ` Andrew Burgess
  2021-02-18 17:32     ` Eli Zaretskii
  2021-03-31 20:11   ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
  3 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-02-18 16:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

From: Tom Tromey <tom@tromey.com>

This adds a new command to change GDB to behave as though "-quiet"
were always given.  This new command can be added to the gdbstartup
file to affect future GDB sessions.

gdb/ChangeLog:

	* NEWS: Add entry.
	* main.c (captured_main_1): Call check_quiet_mode.
	* top.c (startup_quiet): New global.
	(check_quiet_mode): New function.
	(show_startup_quiet): New function.
	(init_main): Register new command.
	* top.h (check_quiet_mode): Declare.

gdb/doc/ChangeLog:

	* gdb.texinfo (Mode Options): Mention "set startup-quietly".

gdb/testsuite/ChangeLog:

	* gdb.base/startup-file.exp: Add more tests.
---
 gdb/ChangeLog                              | 11 ++++++
 gdb/NEWS                                   |  7 ++++
 gdb/doc/ChangeLog                          |  5 +++
 gdb/doc/gdb.texinfo                        |  8 +++++
 gdb/main.c                                 |  5 +++
 gdb/testsuite/ChangeLog                    |  4 +++
 gdb/testsuite/gdb.base/early-init-file.exp | 39 ++++++++++++++++++++++
 gdb/top.c                                  | 33 ++++++++++++++++++
 gdb/top.h                                  |  5 +++
 9 files changed, 117 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index fdd526e86cf..a1d9194de29 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -59,6 +59,13 @@ maintenance flush register-cache
 maintenance flush dcache
   A new command to flush the dcache.
 
+set startup-quietly on|off
+show startup-quietly
+  When 'on', this causes GDB to act as if "-silent" were passed on the
+  command line.  This command needs to be added to an early
+  initialization file (e.g. ~/.config/gdb/gdbearlyinit) in order to
+  affect GDB.
+
 * Changed commands
 
 break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM]
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b900d777c13..2489b69fb23 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1112,6 +1112,14 @@
 ``Quiet''.  Do not print the introductory and copyright messages.  These
 messages are also suppressed in batch mode.
 
+@kindex set startup-quietly
+@kindex show startup-quietly
+This can also be enabled using @code{set startup-quietly on}.  The
+default is @code{off}.  Use @code{show startup-quietly} to see the
+current setting.  Place @code{set startup-quietly on} into your early
+initialization file (@pxref{Initialization Files,,Initialization
+Files}) to have future @value{GDBN} sessions startup quietly.
+
 @item -batch
 @cindex @code{--batch}
 Run in batch mode.  Exit with status @code{0} after processing all the
diff --git a/gdb/main.c b/gdb/main.c
index 5633381fdd5..60c08fb83dd 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -1053,6 +1053,11 @@ captured_main_1 (struct captured_main_args *context)
   execute_cmdargs (&cmdarg_vec, CMDARG_EARLYINIT_FILE,
 		   CMDARG_EARLYINIT_COMMAND, &ret);
 
+  /* 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.  */
   if (set_args)
diff --git a/gdb/testsuite/gdb.base/early-init-file.exp b/gdb/testsuite/gdb.base/early-init-file.exp
index 116a3e83761..701e172656e 100644
--- a/gdb/testsuite/gdb.base/early-init-file.exp
+++ b/gdb/testsuite/gdb.base/early-init-file.exp
@@ -66,6 +66,21 @@ proc setup_home_directories { prefix content } {
     return [list $home_dir $xdg_home_dir]
 }
 
+# Restart GDB and ensure that there's no license text, we should just
+# drop straight to the prompt.
+proc check_gdb_startups_up_quietly { message } {
+    global gdb_prompt
+
+    gdb_exit
+    gdb_spawn
+
+    gdb_test_multiple "" $message {
+	-re "^$gdb_prompt $" {
+	    pass $gdb_test_name
+	}
+    }
+}
+
 save_vars { env(TERM) } {
     # We need an ANSI-capable terminal to get the output.
     setenv TERM ansi
@@ -106,5 +121,29 @@ save_vars { env(TERM) } {
 	check_gdb_startup_version_string none \
 	    "check version string is unstyled using XDG_CONFIG_HOME"
     }
+
+    # Create two directories to use for the quiet startup test.
+    set dirs [setup_home_directories "quiet" "set startup-quietly on"]
+    set home_dir [lindex $dirs 0]
+    set xdg_home_dir [lindex $dirs 1]
+
+    # Now arrange to use the fake home directory startup file.
+    save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+	set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+	# Now test GDB when using the HOME directory.
+	set env(HOME) $home_dir
+	unset -nocomplain env(XDG_CONFIG_HOME)
+	check_gdb_startups_up_quietly \
+	    "check GDB starts quietly using HOME"
+
+	# Now test using the XDG_CONFIG_HOME folder.  We still need to
+	# have a HOME directory set otherwise GDB will issue an error
+	# about not knowing where to place the index cache.
+	set env(XDG_CONFIG_HOME) $xdg_home_dir
+	set env(HOME) $empty_home_dir
+	check_gdb_startups_up_quietly \
+	    "check GDB starts quietly using XDG_CONFIG_HOME"
+    }
 }
 
diff --git a/gdb/top.c b/gdb/top.c
index 3be95079654..07b253ce4be 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -2144,6 +2144,28 @@ set_history_filename (const char *args,
     }
 }
 
+/* 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)
 {
@@ -2298,6 +2320,17 @@ input settings."),
 			show_interactive_mode,
 			&setlist, &showlist);
 
+  c = 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 .gdbstartup 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\
diff --git a/gdb/top.h b/gdb/top.h
index f58bebbb385..9438e52331b 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -291,4 +291,9 @@ extern char *handle_line_of_input (struct buffer *cmd_line_buffer,
 				   const char *rl, int repeat,
 				   const char *annotation_suffix);
 
+/* Call at startup to see if the user has requested that gdb start up
+   quietly.  */
+
+extern bool check_quiet_mode ();
+
 #endif
-- 
2.25.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 3/3] gdb: add "set startup-quietly" command
  2021-02-18 16:41   ` [PATCHv3 3/3] gdb: add "set startup-quietly" command Andrew Burgess
@ 2021-02-18 17:32     ` Eli Zaretskii
  2021-03-24 12:08       ` Andrew Burgess
  0 siblings, 1 reply; 20+ messages in thread
From: Eli Zaretskii @ 2021-02-18 17:32 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, tom

> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Thu, 18 Feb 2021 16:41:04 +0000
> Cc: Tom Tromey <tom@tromey.com>
> 
> gdb/ChangeLog:
> 
> 	* NEWS: Add entry.
> 	* main.c (captured_main_1): Call check_quiet_mode.
> 	* top.c (startup_quiet): New global.
> 	(check_quiet_mode): New function.
> 	(show_startup_quiet): New function.
> 	(init_main): Register new command.
> 	* top.h (check_quiet_mode): Declare.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Mode Options): Mention "set startup-quietly".
> 
> gdb/testsuite/ChangeLog:
> 
> 	* gdb.base/startup-file.exp: Add more tests.

The documentation parts are okay, except that...

> +set startup-quietly on|off
> +show startup-quietly
> +  When 'on', this causes GDB to act as if "-silent" were passed on the
> +  command line.  This command needs to be added to an early
> +  initialization file (e.g. ~/.config/gdb/gdbearlyinit) in order to
> +  affect GDB.                             ^^^^^^^^^^^^
> [...]
> +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 .gdbstartup file in the users home directory to\n\
                          ^^^^^^^^^^^

...there seems to be a disagreement regarding the name of that early
initialization file.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 2/3] gdb: process early initialization files and command line options
  2021-02-18 16:41   ` [PATCHv3 2/3] gdb: process early initialization files and command line options Andrew Burgess
@ 2021-02-18 17:46     ` Eli Zaretskii
  2021-03-24 12:10       ` Andrew Burgess
  0 siblings, 1 reply; 20+ messages in thread
From: Eli Zaretskii @ 2021-02-18 17:46 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Thu, 18 Feb 2021 16:41:03 +0000
> 
> gdb/ChangeLog:
> 
> 	PR cli/25956
> 	* NEWS: Mention new early init files and command line options.
> 	* config.in: Regenerate.
> 	* configure: Regenerate.
> 	* configure.ac: Define GDBEARLYINIT.
> 	* main.c (get_earlyinit_files): New function.
> 	(enum cmdarg_kind): Add CMDARG_EARLYINIT_FILE and
> 	CMDARG_EARLYINIT_COMMAND.
> 	(captured_main_1): Add support for new command line flags, and for
> 	processing startup files.
> 	(print_gdb_help): Include startup files in the output.
> <
> gdb/doc/ChangeLog:
> 
> 	PR cli/25956
> 	* gdb.texinfo (File Options): Mention new command line options.
> 	(Startup): Discuss when early init files are processed.
> 	(Initialization Files): Add description of early init files.
> 	(Output Styling): Update description of 'version' style.
> 	(gdb man): Mention early init files.
> 
> gdb/testsuite/ChangeLog:
> 
> 	PR cli/25956
> 	* gdb.base/early-init-file.c: New file.
> 	* gdb.base/early-init-file.exp: New file.
> 	* lib/gdb-utils.exp (style): Handle style 'none'.

Thanks.

> +* GDB will now load and process commands from ~/.config/gdb/gdbearlyinit
> +  or ~/.gdbearlyinit if these files are present.  These files are
> +  processed earlier than any of the previous initialization files and
                                       ^^^^^^^^
"Previous" is confusing here, since they are actually processed
_after_ .gdbearlyinit.  I suggest "any of the other initialization
files" instead.

> +@item -early-init-command @var{file}
> +@itemx -eix @var{file}
> +@cindex @code{--early-init-command}
> +@cindex @code{-eix}
> +Execute commands from file @var{file} very early in the initialization

It is generally better to say

  Execute commands from @var{file}

thus avoiding identical words one after the other.  When the name in
@var describes itself, there's no need to have the description as
separate text.

> +process, before any output is produced.  @xref{Startup}.
> +
> +@item -early-init-eval-command @var{command}
> +@itemx -eiex @var{command}
> +@cindex @code{--early-init-eval-command}
> +@cindex @code{-eiex}
> +Execute a single @value{GDBN} command very early in the initialization
> +process, before any output is produced.  @xref{Startup}.

You have here two identical cross-references with only a handful of
lines between them.  I'd lose the second one, as it's redundant here.

> +@item
> +Performs minimal setup required to initialise basic internal state.
                                      ^^^^^^^^^^
"initialize", in US spelling, per our conventions.

> +@cindex early initialization file
> +Read commands from the early initialization file (if any) in your home
   ^^^^
"Reads", to be consistent with the other items in this list.

> +directory.  Only a restricted set of commands can be placed into an
> +early initialization file, @pxref{Initialization Files} for details.

This usage of @pxref is problematic: @pxref generally produces a
period after the cross reference, and that looks as a mistake when the
sentence doesn't end there.  So I suggest this instead:

  early initialization file, see @ref{Initialization Files}, for details.

(Note the comma after the closing brace.)

> +Executes commands and command files specified by the @samp{-eiex} and
> +@samp{-eix} command line options in their specified order.  Only a
> +restricted set of commands can be used with @samp{-eiex} and
> +@samp{eix}, @pxref{Initialization Files} for details.

Same here.

> +The @dfn{early initialization} file is loaded very early in
> +@value{GDBN}'s initialization process, before the interpreter

Whenever you introduce a term, which is indicated by the use of @dfn,
it is a good idea to have a @cindex entry for that term, so that
readers could easily find this basic description of the term.

> +In contrast, the @dfn{general initialization} files are processed
> +later, after @value{GDBN} has finished its own internal initialization

Same here.

> +Throughout the rest of this document the term @dfn{initialization
> +file} refers to one of the general initialization files, not the early

And here.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 3/3] gdb: add "set startup-quietly" command
  2021-02-18 17:32     ` Eli Zaretskii
@ 2021-03-24 12:08       ` Andrew Burgess
  0 siblings, 0 replies; 20+ messages in thread
From: Andrew Burgess @ 2021-03-24 12:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, tom

* Eli Zaretskii <eliz@gnu.org> [2021-02-18 19:32:31 +0200]:

> > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > Date: Thu, 18 Feb 2021 16:41:04 +0000
> > Cc: Tom Tromey <tom@tromey.com>
> > 
> > gdb/ChangeLog:
> > 
> > 	* NEWS: Add entry.
> > 	* main.c (captured_main_1): Call check_quiet_mode.
> > 	* top.c (startup_quiet): New global.
> > 	(check_quiet_mode): New function.
> > 	(show_startup_quiet): New function.
> > 	(init_main): Register new command.
> > 	* top.h (check_quiet_mode): Declare.
> > 
> > gdb/doc/ChangeLog:
> > 
> > 	* gdb.texinfo (Mode Options): Mention "set startup-quietly".
> > 
> > gdb/testsuite/ChangeLog:
> > 
> > 	* gdb.base/startup-file.exp: Add more tests.
> 
> The documentation parts are okay, except that...
> 
> > +set startup-quietly on|off
> > +show startup-quietly
> > +  When 'on', this causes GDB to act as if "-silent" were passed on the
> > +  command line.  This command needs to be added to an early
> > +  initialization file (e.g. ~/.config/gdb/gdbearlyinit) in order to
> > +  affect GDB.                             ^^^^^^^^^^^^
> > [...]
> > +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 .gdbstartup file in the users home directory to\n\
>                           ^^^^^^^^^^^
> 
> ...there seems to be a disagreement regarding the name of that early
> initialization file.

Thanks, I have fixed this in my local branch.

Andrew

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 2/3] gdb: process early initialization files and command line options
  2021-02-18 17:46     ` Eli Zaretskii
@ 2021-03-24 12:10       ` Andrew Burgess
  2021-03-24 17:17         ` Eli Zaretskii
  0 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-03-24 12:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Eli,

Thanks for your continued patience in getting the documentation for
this change sorted out.

I believe the revision below addresses your latest feedback.

Again, thanks,

Andrew

---

commit 37434b0d541de76d2567e79f26ba36cb39788a23
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Fri Sep 25 16:28:05 2020 +0100

    gdb: process early initialization files and command line options
    
    Adds the ability to process commands at a new phase during GDB's
    startup.  This phase is earlier than the current initialisation file
    processing, before GDB has produced any output.
    
    The number of commands that can be processed at this early stage will
    be limited, and it is expected that the only commands that would be
    processed at this stage will relate to some of the fundamentals of how
    GDB starts up.
    
    Currently the only commands that it makes sense to add to this early
    initialization file are those like 'set style version ....' as the
    version string is displayed during startup before the standard
    initialization files are parsed.  As such this commit fully resolved
    bug cli/25956.
    
    This commit adds a mechanism to execute these early initialization
    files from a users HOME directory, as well as some corresponding
    command line flags for GDB.
    
    The early initialization files that GDB will currently check for are
    ~/.config/gdb/gdbearlyinit (on Linux like systems) or ~/.gdbearlyinit
    if the former is not found.
    
    The output of 'gdb --help' has been extended to include a list of the
    early initialization files being processed.
    
    gdb/ChangeLog:
    
            PR cli/25956
            * NEWS: Mention new early init files and command line options.
            * config.in: Regenerate.
            * configure: Regenerate.
            * configure.ac: Define GDBEARLYINIT.
            * main.c (get_earlyinit_files): New function.
            (enum cmdarg_kind): Add CMDARG_EARLYINIT_FILE and
            CMDARG_EARLYINIT_COMMAND.
            (captured_main_1): Add support for new command line flags, and for
            processing startup files.
            (print_gdb_help): Include startup files in the output.
    
    gdb/doc/ChangeLog:
    
            PR cli/25956
            * gdb.texinfo (File Options): Mention new command line options.
            (Startup): Discuss when early init files are processed.
            (Initialization Files): Add description of early init files.
            (Output Styling): Update description of 'version' style.
            (gdb man): Mention early init files.
    
    gdb/testsuite/ChangeLog:
    
            PR cli/25956
            * gdb.base/early-init-file.c: New file.
            * gdb.base/early-init-file.exp: New file.
            * lib/gdb-utils.exp (style): Handle style 'none'.

diff --git a/gdb/NEWS b/gdb/NEWS
index 7f5a745d0c0..352996e5d17 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -33,6 +33,18 @@
   the use of the GNAT encoding (based on information added to the type's
   name following a GNAT-specific format).
 
+* GDB will now load and process commands from ~/.config/gdb/gdbearlyinit
+  or ~/.gdbearlyinit if these files are present.  These files are
+  processed earlier than any of the other initialization files and
+  can affect parts of GDB's startup that previously had already been
+  completed before the initialization files were read, for example
+  styling of the initial GDB greeting.
+
+* GDB now has two new options "--early-init-command" and
+  "--early-init-eval-command" with corresponding short options "-eix"
+  and "-eiex" that allow options (that would normally appear in a
+  gdbearlyinit file) to be passed on the command line.
+
 * New commands
 
 set debug event-loop
diff --git a/gdb/config.in b/gdb/config.in
index 14a77c661d5..db860c7cea0 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -43,6 +43,9 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* The .gdbearlyinit filename. */
+#undef GDBEARLYINIT
+
 /* The .gdbinit filename. */
 #undef GDBINIT
 
diff --git a/gdb/configure b/gdb/configure
index 4c80350596c..95fd6b09202 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -16778,6 +16778,12 @@ _ACEOF
 
 
 
+cat >>confdefs.h <<_ACEOF
+#define GDBEARLYINIT ".gdbearlyinit"
+_ACEOF
+
+
+
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
 # except that the argument to --with-sysroot is optional.
 # --with-sysroot (or --with-sysroot=yes) sets the default sysroot path.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 7035014484e..12a59ee45e5 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1819,6 +1819,9 @@ case $host_os in
 esac
 AC_DEFINE_UNQUOTED(GDBINIT,"$gdbinit",[The .gdbinit filename.])
 
+dnl Set the host's .gdbearlyinit filename
+AC_DEFINE_UNQUOTED(GDBEARLYINIT,".gdbearlyinit",[The .gdbearlyinit filename.])
+
 dnl Handle optional features that can be enabled.
 
 # Support for --with-sysroot is a copy of GDB_AC_WITH_DIR,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 80ccf74a049..7f27687b69c 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1040,6 +1040,20 @@
 after loading gdbinit files).
 @xref{Startup}.
 
+@item -early-init-command @var{file}
+@itemx -eix @var{file}
+@cindex @code{--early-init-command}
+@cindex @code{-eix}
+Execute commands from @var{file} very early in the initialization
+process, before any output is produced.  @xref{Startup}.
+
+@item -early-init-eval-command @var{command}
+@itemx -eiex @var{command}
+@cindex @code{--early-init-eval-command}
+@cindex @code{-eiex}
+Execute a single @value{GDBN} command very early in the initialization
+process, before any output is produced.
+
 @item -directory @var{directory}
 @itemx -d @var{directory}
 @cindex @code{--directory}
@@ -1291,6 +1305,23 @@
 Here's the description of what @value{GDBN} does during session startup:
 
 @enumerate
+
+@item
+Performs minimal setup required to initialize basic internal state.
+
+@item
+@cindex early initialization file
+Reads commands from the early initialization file (if any) in your
+home directory.  Only a restricted set of commands can be placed into
+an early initialization file, see @ref{Initialization Files}, for
+details.
+
+@item
+Executes commands and command files specified by the @samp{-eiex} and
+@samp{-eix} command line options in their specified order.  Only a
+restricted set of commands can be used with @samp{-eiex} and
+@samp{eix}, see @ref{Initialization Files}, for details.
+
 @item
 Sets up the command interpreter as specified by the command line
 (@pxref{Mode Options, interpreter}).
@@ -1367,13 +1398,82 @@
 startup, in the order they will be loaded, you can use @kbd{gdb
 --help}.
 
+@cindex early initialization
+The @dfn{early initialization} file is loaded very early in
+@value{GDBN}'s initialization process, before the interpreter
+(@pxref{Interpreters}) has been initialized, and before the default
+target (@pxref{Targets}) is initialized.  Only @code{set} or
+@code{source} commands should be placed into an early initialization
+file, and the only @code{set} commands that can be used are those that
+control how @value{GDBN} starts up.
+
+Commands that can be placed into an early initialization file will be
+documented as such throughout this manual.  Any command that is not
+documented as being suitable for an early initialization file should
+instead be placed into a general initialization file.  Command files
+passed to @code{--early-init-command} or @code{-eix} are also early
+initialization files, with the same command restrictions.  Only
+commands that can appear in an early initialization file should be
+passed to @code{--early-init-eval-command} or @code{-eiex}.
+
+@cindex general initialization
+In contrast, the @dfn{general initialization} files are processed
+later, after @value{GDBN} has finished its own internal initialization
+process, any valid command can be used in these files.
+
+@cindex initialization file
+Throughout the rest of this document the term @dfn{initialization
+file} refers to one of the general initialization files, not the early
+initialization file.  Any discussion of the early initialization file
+will specifically mention that it is the early initialization file
+being discussed.
+
 As the system wide and home directory initialization files are
 processed before most command line options, changes to settings
 (e.g. @samp{set complaints}) can affect subsequent processing of
 command line options and operands.
 
-The following sections describe where @value{GDBN} looks for the
-initialization and the order that the files are searched for.
+The following sections describe where @value{GDBN} looks for the early
+initialization and initialization files, and the order that the files
+are searched for.
+
+@subsubsection Home directory early initialization files
+
+@value{GDBN} initially looks for an early initialization file in the
+users home directory@footnote{On DOS/Windows systems, the home
+directory is the one pointed to by the @code{HOME} environment
+variable.}.  There are a number of locations that @value{GDBN} will
+search in the home directory, these locations are searched in order
+and @value{GDBN} will load the first file that it finds, and
+subsequent locations will not be checked.
+
+On non-macOS hosts the locations searched are:
+@itemize
+@item
+The file @file{gdb/gdbearlyinit} within the directory pointed to by the
+environment variable @env{XDG_CONFIG_HOME}, if it is defined.
+@item
+The file @file{.config/gdb/gdbearlyinit} within the directory pointed to
+by the environment variable @env{HOME}, if it is defined.
+@item
+The file @file{.gdbearlyinit} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+By contrast, on macOS hosts the locations searched are:
+@itemize
+@item
+The file @file{Library/Preferences/gdb/gdbearlyinit} within the
+directory pointed to by the environment variable @env{HOME}, if it is
+defined.
+@item
+The file @file{.gdbearlyinit} within the directory pointed to by the
+environment variable @env{HOME}, if it is defined.
+@end itemize
+
+It is possible to prevent the home directory early initialization file
+from being loaded using the @samp{-nx} or @samp{-nh} command line
+options, @pxref{Mode Options,,Choosing Modes}.
 
 @anchor{System Wide Init Files}
 @subsubsection System wide initialization files
@@ -25821,11 +25921,10 @@
 intensity.  The version number is displayed in two places, the output
 of @command{show version}, and when @value{GDBN} starts up.
 
-Currently the version string displayed at startup is printed before
-@value{GDBN} has parsed any command line options, or parsed any
-command files, so there is currently no way to control the styling of
-this string.  However, @value{GDBN}'s @code{--quiet} command line option
-can be used to disable printing of the version string on startup.
+In order to control how @value{GDBN} styles the version number at
+startup, add the @code{set style version} family of commands to the
+early initialization command file (@pxref{Initialization
+Files}).
 
 @item title
 Control the styling of titles.  These are managed with the
@@ -46630,12 +46729,14 @@
 Add @var{directory} to the path to search for source files.
 
 @item -nh
-Do not execute commands from @file{~/.config/gdb/gdbinit} or
-@file{~/.gdbinit}.
+Do not execute commands from @file{~/.config/gdb/gdbinit},
+@file{~/.gdbinit}, @file{~/.config/gdb/gdbearlyinit}, or
+@file{~/.gdbearlyinit}
 
 @item -nx
 @itemx -n
-Do not execute commands from any @file{.gdbinit} initialization files.
+Do not execute commands from any @file{.gdbinit} or
+@file{.gdbearlyinit} initialization files.
 
 @item -quiet
 @itemx -q
diff --git a/gdb/main.c b/gdb/main.c
index 2ba39273d07..5633381fdd5 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -386,6 +386,22 @@ get_init_files (std::vector<std::string> *system_gdbinit,
   *local_gdbinit = init_files->local_file ();
 }
 
+/* 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
+get_earlyinit_files (std::string *home_gdbearlyinit)
+{
+  /* 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 ();
+}
+
 /* Start up the event loop.  This is the entry point to the event loop
    from the command loop.  */
 
@@ -560,7 +576,13 @@ enum cmdarg_kind
   CMDARG_INIT_FILE,
     
   /* Option type -iex.  */
-  CMDARG_INIT_COMMAND
+  CMDARG_INIT_COMMAND,
+
+  /* Option type -sx.  */
+  CMDARG_EARLYINIT_FILE,
+
+  /* Option type -sex.  */
+  CMDARG_EARLYINIT_COMMAND
 };
 
 /* Arguments of --command option and its counterpart.  */
@@ -738,6 +760,8 @@ captured_main_1 (struct captured_main_args *context)
       OPT_WINDOWS,
       OPT_IX,
       OPT_IEX,
+      OPT_EIX,
+      OPT_EIEX,
       OPT_READNOW,
       OPT_READNEVER
     };
@@ -787,6 +811,10 @@ captured_main_1 (struct captured_main_args *context)
       {"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'},
@@ -899,6 +927,12 @@ captured_main_1 (struct captured_main_args *context)
 	  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 ();
@@ -1007,6 +1041,18 @@ captured_main_1 (struct captured_main_args *context)
   /* Initialize all files.  */
   gdb_init (gdb_program_name);
 
+  /* 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);
+
   /* Now that gdb_init has created the initial inferior, we're in
      position to set args for that inferior.  */
   if (set_args)
@@ -1334,8 +1380,10 @@ print_gdb_help (struct ui_file *stream)
   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
@@ -1409,6 +1457,17 @@ Other options:\n\n\
 		     Set GDB's data-directory to DIR.\n\
 "), stream);
   fputs_unfiltered (_("\n\
+At startup, GDB reads the following early init files and executes their\n\
+commands:\n\
+"), stream);
+  if (!home_gdbearlyinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   * user-specific early init file: %s\n\
+"), home_gdbearlyinit.c_str ());
+  if (home_gdbearlyinit.empty ())
+    fprintf_unfiltered (stream, _("\
+   None found.\n"));
+  fputs_unfiltered (_("\n\
 At startup, GDB reads the following init files and executes their commands:\n\
 "), stream);
   if (!system_gdbinit.empty ())
diff --git a/gdb/testsuite/gdb.base/early-init-file.c b/gdb/testsuite/gdb.base/early-init-file.c
new file mode 100644
index 00000000000..9811b15f06d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/early-init-file.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/early-init-file.exp b/gdb/testsuite/gdb.base/early-init-file.exp
new file mode 100644
index 00000000000..4873e5be3ae
--- /dev/null
+++ b/gdb/testsuite/gdb.base/early-init-file.exp
@@ -0,0 +1,109 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test GDB's early init file mechanism.
+
+standard_testfile
+
+# Compile the test executable.
+if {[build_executable "failed to build" $testfile $srcfile]} {
+    return -1
+}
+
+# Start gdb and ensure that the initial version string is styled in
+# STYLE, use MESSAGE as the name of the test.
+proc check_gdb_startup_version_string { style { message "" } } {
+    if { $message == "" } {
+	set message "check startup version string has style $style"
+    }
+
+    gdb_exit
+    gdb_spawn
+    set vers [style "GNU gdb.*" $style]
+    gdb_test "" "^${vers}.*" $message
+}
+
+# Return a list containing two directory paths for newly created home
+# directories.
+#
+# The first directory is a HOME style home directory, it contains a
+# .gdbearlyinit file containing CONTENT.
+#
+# The second directory is an XDG_CONFIG_HOME style home directory, it
+# contains a sub-directory gdb/, inside which is a file gdbearlyinit
+# that also contains CONTENT.
+#
+# The PREFIX is used in both directory names and should be unique for
+# each call to this function.
+proc setup_home_directories { prefix content } {
+    set home_dir [standard_output_file "${prefix}-home"]
+    set xdg_home_dir [standard_output_file "${prefix}-xdg"]
+
+    file mkdir $home_dir
+    file mkdir "$xdg_home_dir/gdb"
+
+    # Write the content into the HOME directory.
+    set fd [open "$home_dir/.gdbearlyinit" w]
+    puts $fd $content
+    close $fd
+
+    # Copy this from the HOME directory into the XDG_CONFIG_HOME
+    # directory.
+    file copy -force "$home_dir/.gdbearlyinit" "$xdg_home_dir/gdb/gdbearlyinit"
+
+    return [list $home_dir $xdg_home_dir]
+}
+
+save_vars { env(TERM) } {
+    # We need an ANSI-capable terminal to get the output.
+    setenv TERM ansi
+
+    # Start GDB and confirm that the version string is styled.
+    check_gdb_startup_version_string version
+
+    # Create an empty directory we can use as HOME for some of the
+    # tests below.  When we set XDG_CONFIG_HOME we still need to point
+    # HOME at something otherwise GDB complains that it doesn't know
+    # where to create the index cache.
+    set empty_home_dir [standard_output_file fake-empty-home]
+
+    # Create two directories to use for the style setting test.
+    set dirs [setup_home_directories "style" \
+		  [multi_line_input \
+		       "set style version foreground none" \
+		       "set style version background none" \
+		       "set style version intensity normal"]]
+    set home_dir [lindex $dirs 0]
+    set xdg_home_dir [lindex $dirs 1]
+
+    # Now arrange to use the fake home directory early init file.
+    save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+	set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+	# Now test GDB when using the HOME directory.
+	set env(HOME) $home_dir
+	unset -nocomplain env(XDG_CONFIG_HOME)
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using HOME"
+
+	# Now test using the XDG_CONFIG_HOME folder.  We still need to
+	# have a HOME directory set otherwise GDB will issue an error
+	# about not knowing where to place the index cache.
+	set env(XDG_CONFIG_HOME) $xdg_home_dir
+	set env(HOME) $empty_home_dir
+	check_gdb_startup_version_string none \
+	    "check version string is unstyled using XDG_CONFIG_HOME"
+    }
+}
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index ad7d2884aae..cec157196b3 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -56,6 +56,7 @@ proc style {str style} {
 	address { set style 34 }
 	metadata { set style 2 }
 	version { set style "35;1" }
+	none { return $str }
     }
     return "\033\\\[${style}m${str}\033\\\[m"
 }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 2/3] gdb: process early initialization files and command line options
  2021-03-24 12:10       ` Andrew Burgess
@ 2021-03-24 17:17         ` Eli Zaretskii
  0 siblings, 0 replies; 20+ messages in thread
From: Eli Zaretskii @ 2021-03-24 17:17 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Wed, 24 Mar 2021 12:10:08 +0000
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Cc: gdb-patches@sourceware.org
> 
> Eli,
> 
> Thanks for your continued patience in getting the documentation for
> this change sorted out.
> 
> I believe the revision below addresses your latest feedback.

It does, thanks.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 0/3] Adding startup files to GDB
  2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
                     ` (2 preceding siblings ...)
  2021-02-18 16:41   ` [PATCHv3 3/3] gdb: add "set startup-quietly" command Andrew Burgess
@ 2021-03-31 20:11   ` Andrew Burgess
  2021-04-02 19:20     ` Tom Tromey
  3 siblings, 1 reply; 20+ messages in thread
From: Andrew Burgess @ 2021-03-31 20:11 UTC (permalink / raw)
  To: gdb-patches

Final Ping!

With lots of help from Eli the docs are now looking good.  So I'm
planning to push this series in the new few days, unless anyone would
like to object.

Thanks,
Andrew



* Andrew Burgess <andrew.burgess@embecosm.com> [2021-02-18 16:41:01 +0000]:

> Changes since v2:
> 
> Patch #1
> 
>  - Make use of gdb::optional as Simon suggested.
> 
> Patch #2
> 
>  - Rename 'startup' files to 'earlyinit' files as Simon suggested.
> 
>  - Extensive documentation changes to address Eli's feedback, and to
>    reflect the naming change.
> 
>  - Renamed the test script to reflect the naming change.
> 
> Patch #3
> 
>  - Updates to the documentation to (I hope) address Eli's feedback.
> 
> 
> Thanks,
> Andrew
> 
> ---
> 
> Andrew Burgess (2):
>   gdb: refactor the initialization file lookup code
>   gdb: process early initialization files and command line options
> 
> Tom Tromey (1):
>   gdb: add "set startup-quietly" command
> 
>  gdb/ChangeLog                              |  33 +++
>  gdb/NEWS                                   |  19 ++
>  gdb/config.in                              |   3 +
>  gdb/configure                              |   6 +
>  gdb/configure.ac                           |   3 +
>  gdb/doc/ChangeLog                          |  14 ++
>  gdb/doc/gdb.texinfo                        | 125 +++++++++-
>  gdb/main.c                                 | 253 +++++++++++++++------
>  gdb/testsuite/ChangeLog                    |  11 +
>  gdb/testsuite/gdb.base/early-init-file.c   |  22 ++
>  gdb/testsuite/gdb.base/early-init-file.exp | 149 ++++++++++++
>  gdb/testsuite/lib/gdb-utils.exp            |   1 +
>  gdb/top.c                                  |  33 +++
>  gdb/top.h                                  |   5 +
>  14 files changed, 603 insertions(+), 74 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.base/early-init-file.c
>  create mode 100644 gdb/testsuite/gdb.base/early-init-file.exp
> 
> -- 
> 2.25.4
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv3 0/3] Adding startup files to GDB
  2021-03-31 20:11   ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
@ 2021-04-02 19:20     ` Tom Tromey
  0 siblings, 0 replies; 20+ messages in thread
From: Tom Tromey @ 2021-04-02 19:20 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

Andrew> With lots of help from Eli the docs are now looking good.  So I'm
Andrew> planning to push this series in the new few days, unless anyone would
Andrew> like to object.

Looks good to me.  Thanks for advancing this.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2021-04-02 19:20 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-26  9:48 [PATCHv2 0/3] Adding startup files to GDB Andrew Burgess
2021-01-26  9:48 ` [PATCHv2 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
2021-01-26 15:09   ` Simon Marchi
2021-01-26  9:48 ` [PATCHv2 2/3] gdb: process startup files and startup command line options Andrew Burgess
2021-01-26 15:22   ` Eli Zaretskii
2021-01-26 15:32     ` Simon Marchi
2021-01-26 15:30   ` Simon Marchi
2021-01-26  9:48 ` [PATCHv2 3/3] gdb: add "set startup-quietly" command Andrew Burgess
2021-01-26 15:12   ` Eli Zaretskii
2021-02-18 16:41 ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
2021-02-18 16:41   ` [PATCHv3 1/3] gdb: refactor the initialization file lookup code Andrew Burgess
2021-02-18 16:41   ` [PATCHv3 2/3] gdb: process early initialization files and command line options Andrew Burgess
2021-02-18 17:46     ` Eli Zaretskii
2021-03-24 12:10       ` Andrew Burgess
2021-03-24 17:17         ` Eli Zaretskii
2021-02-18 16:41   ` [PATCHv3 3/3] gdb: add "set startup-quietly" command Andrew Burgess
2021-02-18 17:32     ` Eli Zaretskii
2021-03-24 12:08       ` Andrew Burgess
2021-03-31 20:11   ` [PATCHv3 0/3] Adding startup files to GDB Andrew Burgess
2021-04-02 19:20     ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).