]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add "save skip" command
authorTom Tromey <tom@tromey.com>
Tue, 24 Jan 2023 00:04:55 +0000 (17:04 -0700)
committerTom Tromey <tom@tromey.com>
Thu, 19 Feb 2026 00:33:50 +0000 (17:33 -0700)
PR cli/17997 points out that it would sometimes be convenient to save
the current "skip"s to a file.  This patch implements this feature.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17997
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Keith Seitz <keiths@redhat.com>
gdb/NEWS
gdb/doc/gdb.texinfo
gdb/skip.c
gdb/testsuite/gdb.base/skip.exp

index e9a8022bdfa0f4582343b49e23bef1d570498411..888d1a468b3e1bb9680287540af82d8306962426 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -81,6 +81,9 @@ unset local-environment
   environment.  The local environment is used by "shell", "pipe", and
   other commands that launch a subprocess other than an inferior.
 
+save skip FILENAME
+  Save all current "skip"s to the given file.
+
 save user FILENAME
   Save all user-defined commands to the given file.
 
index 5d90785be4abe2b09d540b841be14f5818a20060..92e7366428165e4a47144d12472b6903bd74d132 100644 (file)
@@ -7070,6 +7070,12 @@ skips.
 Disable the specified skip(s).  If @var{range} is not specified, disable all
 skips.
 
+@kindex save skip
+@item save skip @var{filename}
+Save all skips to the file @var{filename}.  This command writes out
+the skips as a script that can be re-read into @value{GDBN} using the
+@code{source} command.
+
 @kindex set debug skip
 @item set debug skip @r{[}on|off@r{]}
 Set whether to print the debug output about skipping files and functions.
index f4156d93d4071cde9c56dea27c7ae6d09e2824f1..ea8e9a210afa586163737e9d20e589bebd4a3c67 100644 (file)
@@ -38,6 +38,8 @@
 #include <list>
 #include "cli/cli-style.h"
 #include "gdbsupport/buildargv.h"
+#include "safe-ctype.h"
+#include "readline/tilde.h"
 
 /* True if we want to print debug printouts related to file/function
    skipping. */
@@ -72,6 +74,9 @@ public:
   void enable () { m_enabled = true; };
   void disable () { m_enabled = false; };
 
+  /* Print a gdb command that can be used to recreate this skip.  */
+  void print_recreate (ui_file *stream) const;
+
 private:
   /* Key that grants access to the constructor.  */
   struct private_key {};
@@ -159,6 +164,54 @@ skiplist_entry::add_entry (bool file_is_glob, std::string &&file,
   skiplist_entries.back ().m_number = ++highest_skiplist_entry_num;
 }
 
+/* A helper function for print_recreate that prints a correctly-quoted
+   string to STREAM.  */
+
+static void
+print_quoted (ui_file *stream, const std::string &str)
+{
+  gdb_putc ('"', stream);
+  for (char c : str)
+    {
+      if (ISSPACE (c) || c == '\\' || c == '\'' || c == '"')
+       gdb_putc ('\\', stream);
+      gdb_putc (c, stream);
+    }
+  gdb_putc ('"', stream);
+}
+
+void
+skiplist_entry::print_recreate (ui_file *stream) const
+{
+  if (!m_file_is_glob && !m_file.empty ()
+      && !m_function_is_regexp && m_function.empty ())
+    gdb_printf (stream, "skip file %s\n", m_file.c_str ());
+  else if (!m_file_is_glob && m_file.empty ()
+      && !m_function_is_regexp && !m_function.empty ())
+    gdb_printf (stream, "skip function %s\n", m_function.c_str ());
+  else
+    {
+      gdb_printf (stream, "skip ");
+      if (!m_file.empty ())
+       {
+         if (m_file_is_glob)
+           gdb_printf (stream, "-gfile ");
+         else
+           gdb_printf (stream, "-file ");
+         print_quoted (stream, m_file);
+       }
+      if (!m_function.empty ())
+       {
+         if (m_function_is_regexp)
+           gdb_printf (stream, "-rfunction ");
+         else
+           gdb_printf (stream, "-function ");
+         print_quoted (stream, m_function);
+       }
+      gdb_printf (stream, "\n");
+    }
+}
+
 static void
 skip_file_command (const char *arg, int from_tty)
 {
@@ -656,6 +709,24 @@ complete_skip_number (cmd_list_element *cmd,
     }
 }
 
+/* Implementation of 'save skip' command.  */
+
+static void
+save_skip_command (const char *filename, int from_tty)
+{
+  if (filename == nullptr || *filename == '\0')
+    error (_("Argument required (file name in which to save)"));
+
+  gdb::unique_xmalloc_ptr<char> expanded_filename (tilde_expand (filename));
+  stdio_file fp;
+  if (!fp.open (expanded_filename.get (), "w"))
+    error (_("Unable to open file '%s' for saving (%s)"),
+          expanded_filename.get (), safe_strerror (errno));
+
+  for (const auto &entry : skiplist_entries)
+    entry.print_recreate (&fp);
+}
+
 INIT_GDB_FILE (step_skip)
 {
   static struct cmd_list_element *skiplist = NULL;
@@ -734,4 +805,11 @@ Show whether the debug output about skipping files and functions is printed."),
 When non-zero, debug output about skipping files and functions is displayed."),
                           NULL, NULL,
                           &setdebuglist, &showdebuglist);
+
+  c = add_cmd ("skip", no_class, save_skip_command, _("\
+Save current skips as a script.\n\
+Usage: save skip FILE\n\
+Use the 'source' command in another debug session to restore them."),
+              &save_cmdlist);
+  set_cmd_completer (c, deprecated_filename_completer);
 }
index 4541e61ec007195f522e9fe785d5a7aea2e17378..ea9eaf9c0e5feece9866138f190b52540e31edaf 100644 (file)
@@ -206,6 +206,9 @@ with_test_prefix "admin" {
                    "4\\s+y\\s+n\\s+<none>\\s+n\\s+baz"] \
        "info skip after enabling all"
 
+    gdb_test_no_output "save skip [standard_output_file skips]" \
+       "save skips to file"
+
     gdb_test "skip disable 4 2-3"
     gdb_test "info skip" \
        [multi_line "Num\\s+Enb\\s+Glob\\s+File\\s+RE\\s+Function" \
@@ -336,3 +339,13 @@ with_test_prefix "skip delete completion" {
     test_gdb_complete_none "skip delete a1"
     test_gdb_complete_none "skip delete 2-33"
 }
+
+clean_restart
+gdb_test "source [standard_output_file skips]" "" \
+    "re-read saved skips"
+gdb_test "info skip" \
+    [multi_line "Num\\s+Enb\\s+Glob\\s+File\\s+RE\\s+Function" \
+        "1\\s+y\\s+n\\s+<none>\\s+n\\s+main" \
+        "2\\s+y\\s+n\\s+$srcfile1\\s+n\\s+<none>" \
+        "3\\s+y\\s+n\\s+<none>\\s+n\\s+baz"] \
+    "info skip after re-reading"