[PATCH v2 3/7] Add "tips" file to gdb

Tom Tromey
2020-06-23T13:20:09Z

This adds a "tips" file to gdb. This file holds handy tips -- right
now there are just a few, but it's easy to add more. A random tip is
displayed during interactive startup.

gdb/ChangeLog
2020-06-22 Tom Tromey <tom@tromey.com>

* NEWS: Add entry.
* top.c (startup_style): New global.
(print_tip): New function.
(print_gdb_version): Update. Don't print "show configuration"
or "apropos" info. Call print_tip.
* tips: New file.
* data-directory/Makefile.in (GDB_FILES): Add "tips".

gdb/doc/ChangeLog
2020-06-22 Tom Tromey <tom@tromey.com>

* gdb.texinfo (Help): Mention tips.
---
gdb/ChangeLog | 10 +++++
gdb/NEWS | 2 +
gdb/data-directory/Makefile.in | 2 +-
gdb/doc/ChangeLog | 4 ++
gdb/doc/gdb.texinfo | 3 ++
gdb/tips | 9 ++++
gdb/top.c | 78 +++++++++++++++++++++++++++++-----
7 files changed, 96 insertions(+), 12 deletions(-)
create mode 100644 gdb/tips

diff --git a/gdb/NEWS b/gdb/NEWS
index 0fd39857326..e977630c445 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,8 @@

*** Changes since GDB 9

+* GDB will now display a helpful tip when starting up.
+
* Help and apropos commands will now show the documentation of a
command only once, even if that command has one or more aliases.
These commands now show the command name, then all of its aliases,
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
index 85a2f41c351..b3c1243e832 100644
--- a/gdb/data-directory/Makefile.in
+++ b/gdb/data-directory/Makefile.in
@@ -139,7 +139,7 @@ SYSTEM_GDBINIT_FILES = \
elinos.py \
wrs-linux.py

-GDB_FILES = NEWS
+GDB_FILES = NEWS tips

FLAGS_TO_PASS = \
"prefix=$(prefix)" \
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 37d5fe1e4cd..0a74992fbac 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2324,6 +2324,9 @@ automatically by @command{configure}. When reporting a @value{GDBN}
bug (@pxref{GDB Bugs}), it is important to include this information in
your report.

+Finally, unless @code{--quiet} is used, @value{GDBN} will print a
+helpful tip at startup.
+
@end table

@node Running
diff --git a/gdb/tips b/gdb/tips
new file mode 100644
index 00000000000..75957fb853d
--- /dev/null
+++ b/gdb/tips
@@ -0,0 +1,9 @@
+This file is in the old "fortune" format. Each entry is separated by
+a percent character on a line of its own. Anything before the first
+percent will never be shown.
+%
+You can use "help news" to see what has changed in GDB.
+%
+Type "apropos word" to search for commands related to "word".
+%
+Type "show configuration" for configuration details.
diff --git a/gdb/top.c b/gdb/top.c
index da9b805b479..62a2c706031 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -56,6 +56,8 @@
#include "gdbarch.h"
#include "gdbsupport/pathstuff.h"
#include "cli/cli-style.h"
+#include "gdbsupport/scoped_fd.h"
+#include <random>

/* readline include files. */
#include "readline/readline.h"
@@ -128,6 +130,14 @@ current_ui_current_uiout_ptr ()

int inhibit_gdbinit = 0;

+/* The style used for informational messages at startup. */
+static ui_file_style startup_style =
+{
+ ui_file_style::MAGENTA,
+ ui_file_style::NONE,
+ ui_file_style::BOLD
+};
+
/* Flag for whether we want to confirm potentially dangerous
operations. Default is yes. */

@@ -1389,6 +1399,59 @@ command_line_input (const char *prompt_arg, const char *annotation_suffix)
return cmd;
}
\f
+
+/* Print a useful tip to STREAM. */
+
+static void
+print_tip (struct ui_file *stream)
+{
+ std::string tip_name = std::string (gdb_datadir) + SLASH_STRING + "tips";
+ scoped_fd fd (gdb_open_cloexec (tip_name.c_str (), O_RDONLY | O_BINARY, 0));
+ if (fd.get () < 0)
+ {
+ perror_warning_with_name ((std::string (_("Could not open tip file "))
+ + tip_name).c_str ());
+ return;
+ }
+
+ std::string lines;
+ try
+ {
+ lines = read_entire_file (tip_name.c_str (), fd.get ());
+ }
+ catch (const gdb_exception &exc)
+ {
+ exception_print (stream, exc);
+ return;
+ }
+
+ std::vector<gdb::string_view> strings;
+ size_t offset = lines.find ("%\n");
+ if (offset == std::string::npos)
+ return;
+ while (offset != std::string::npos)
+ {
+ offset += 2;
+ size_t next_offset = lines.find ("%\n", offset);
+
+ if (next_offset == std::string::npos)
+ strings.emplace_back (lines.c_str () + offset);
+ else
+ strings.emplace_back (lines.c_str () + offset, next_offset - offset);
+
+ offset = next_offset;
+ }
+
+ std::random_device rd;
+ std::mt19937 mt (rd ());
+ std::uniform_int_distribution<> distr (0, strings.size () - 1);
+ int index = distr (mt);
+ /* Note that the string will include a newline. */
+ fprintf_styled (stream, startup_style, "\n%.*s",
+ (int) strings[index].size (),
+ strings[index].data ());
+}
+
/* See top.h. */
void
print_gdb_version (struct ui_file *stream, bool interactive)
@@ -1399,11 +1462,7 @@ print_gdb_version (struct ui_file *stream, bool interactive)

ui_file_style style;
if (interactive)
- {
- ui_file_style nstyle = { ui_file_style::MAGENTA, ui_file_style::NONE,
- ui_file_style::BOLD };
- style = nstyle;
- }
+ style = startup_style;
fprintf_styled (stream, style, "GNU gdb %s%s\n", PKGVERSION, version);

/* Second line is a copyright notice. */
@@ -1441,9 +1500,6 @@ There is NO WARRANTY, to the extent permitted by law.");
}
fprintf_filtered (stream, "\".\n");

- fprintf_filtered (stream, _("Type \"show configuration\" "
- "for configuration details.\n"));
-
if (REPORT_BUGS_TO[0])
{
fprintf_filtered (stream,
@@ -1455,9 +1511,9 @@ There is NO WARRANTY, to the extent permitted by law.");
resources online at:\n <http://www.gnu.org/software/gdb/documentation/>."));
fprintf_filtered (stream, "\n\n");
fprintf_filtered (stream, _("For help, type \"help\".\n"));
- fprintf_filtered (stream,
- _("Type \"apropos word\" to search for commands \
-related to \"word\"."));
+
+ if (interactive)
+ print_tip (stream);
}

/* Print the details of GDB build-time configuration. */
--
2.17.2