gdb/cli: Improve UX when using list with no args
authorBruno Larsen <blarsen@redhat.com>
Thu, 15 Jun 2023 09:17:07 +0000 (11:17 +0200)
committerBruno Larsen <blarsen@redhat.com>
Fri, 14 Jul 2023 08:58:17 +0000 (10:58 +0200)
When using "list" with no arguments, GDB will first print the lines
around where the inferior is stopped, then print the next N lines until
reaching the end of file, at which point it warns the user "Line X out
of range, file Y only has X-1 lines.".  This is usually desirable, but
if the user can no longer see the original line, they may have forgotten
the current line or that a list command was used at all, making GDB's
error message look cryptic. It was reported in bugzilla as PR cli/30497.

This commit improves the user experience by changing the behavior of
"list" slightly when a user passes no arguments.  It now prints that the
end of the file has been reached and recommends that the user use the
command "list ." instead.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30497
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
gdb/NEWS
gdb/cli/cli-cmds.c
gdb/doc/gdb.texinfo
gdb/source.c
gdb/source.h
gdb/testsuite/gdb.base/list.exp

index c5bbd4f134800cb2b836a8922139d89f296c4392..ac5dc424d3f72e0ca8da29f6f8c1e4af3bc673e3 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
   print the location where the inferior is stopped.  If the inferior hasn't
   started yet, the command will print around the main function.
 
+* Using the 'list' command with no arguments in a situation where the
+  command would attempt to list past the end of the file now warns the
+  user that the end of file has been reached, refers the user to the
+  newly added '.' argument
+
 * New commands
 
 maintenance print record-instruction [ N ]
index 44db019c59f17ba338f5379fa73ce521f5d86132..3a1902a0c82f1fbe230ee474a0ab850f3b6e5724 100644 (file)
@@ -1246,10 +1246,19 @@ list_command (const char *arg, int from_tty)
          list_around_line (arg, cursal);
        }
 
-      /* "l" or "l +" lists next ten lines.  */
-      else if (arg == NULL || arg[0] == '+')
-       print_source_lines (cursal.symtab,
-                           source_lines_range (cursal.line), 0);
+      /* "l" and "l +" lists the next few lines, unless we're listing past
+        the end of the file.  */
+      else if (arg == nullptr || arg[0] == '+')
+       {
+         if (last_symtab_line (cursal.symtab) >= cursal.line)
+           print_source_lines (cursal.symtab,
+                               source_lines_range (cursal.line), 0);
+         else
+           {
+             error (_("End of the file was already reached, use \"list .\" to"
+                      " list the current location again"));
+           }
+       }
 
       /* "l -" lists previous ten lines, the ones before the ten just
         listed.  */
index 7619efe3de93b71083a08d64e1cae005604bd4c3..20c9b24400dbe4a4ada465e93402d9d10af440cd 100644 (file)
@@ -9144,7 +9144,9 @@ Print more lines.  If the last lines printed were printed with a
 @code{list} command, this prints lines following the last lines
 printed; however, if the last line printed was a solitary line printed
 as part of displaying a stack frame (@pxref{Stack, ,Examining the
-Stack}), this prints lines centered around that line.
+Stack}), this prints lines centered around that line.  If no
+@code{list} command has been used and no solitary line was printed,
+it prints the lines around the function @code{main}.
 
 @item list -
 Print lines just before the lines last printed.
index 9997cccb31be6351adfcb0640659b804a2397469..08adc6671b7b938c44a5c1b373f970e0ee6034c3 100644 (file)
@@ -1484,6 +1484,22 @@ print_source_lines (struct symtab *s, source_lines_range line_range,
                           line_range.stopline (), flags);
 }
 
+/* See source.h.  */
+
+int
+last_symtab_line (struct symtab *s)
+{
+  const std::vector<off_t> *offsets;
+
+  /* Try to get the offsets for the start of each line.  */
+  if (!g_source_cache.get_line_charpos (s, &offsets))
+    return false;
+  if (offsets == nullptr)
+    return false;
+
+  return offsets->size ();
+}
+
 
 \f
 /* Print info on range of pc's in a specified line.  */
index 8fbc365680d47e5697f8df4318a3c9a711c69df5..be80e00389096b9029b67545c213c417824041a5 100644 (file)
@@ -192,6 +192,13 @@ private:
   int m_stopline;
 };
 
+/* Get the number of the last line in the given symtab.  */
+extern int last_symtab_line (struct symtab *s);
+
+/* Check if the line LINE can be found in the symtab S, so that it can be
+   printed.  */
+extern bool can_print_line (struct symtab *s, int line);
+
 /* Variation of previous print_source_lines that takes a range instead of a
    start and end line number.  */
 extern void print_source_lines (struct symtab *s, source_lines_range r,
index ed178a1dd95f8ad08fdcc1955b40142cda6305d5..582355996b0870f38d8e92d782eb4edf3eeb0da0 100644 (file)
@@ -175,8 +175,8 @@ proc_with_prefix test_list_forward {} {
        "list 25-34"
     gdb_test "list" "35\[ \t\]+foo \\(.*\\);.*${last_line_re}" \
        "list 35-42"
-    gdb_test "list" "Line number 44 out of range; \[^\r\n\]+ has 43 lines\." \
-       "end of file error after \"list\" command"
+    gdb_test "list" "End of the file was already reached, use \"list .\" to list the current location again" \
+       "list past end of file"
 }
 
 # Test that repeating the list linenum command doesn't print the same
@@ -194,8 +194,8 @@ proc_with_prefix test_repeat_list_command {} {
        "list 25-34"
     gdb_test " " "35\[ \t\]+foo \\(.*\\);.*${last_line_re}" \
        "list 35-42"
-    gdb_test "list" "Line number 44 out of range; \[^\r\n\]+ has 43 lines\." \
-       "end of file error after using 'return' to repeat the list command"
+    gdb_test "list" "End of the file was already reached, use \"list .\" to list the current location again" \
+       "list past end of file"
 }
 
 proc_with_prefix test_list_backwards {} {