Re: [2/2] RFC: let "commands" affect multiple breakpoints

Pedro Alves
2010-03-25T17:09:51Z

On Wednesday 24 March 2010 21:21:08, Tom Tromey wrote:
> I'm checking in the appended. This is the revised patch, rebased on top
> of Volodya's patches.

Thanks.

<In an earlier email, Tom said:>

> I do have a question though. With this change, gdb prints somewhat less
> nice text for "commands":
>
> Tom> + l = read_command_lines (_("Type commands for all specified breakpoints"),
> Tom> + info->from_tty, 1);
>
> Tom> - char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.",
> Tom> - bnum);
>
> Any suggestions for something better here?

I have a suggestion for this, in form of a patch. How
about we just print the breakpoint range? I find this:

(top-gdb) rbreak main
...
...
(top-gdb) commands
Type commands for breakpoint(s) 3-80, one per line.
End with a line saying just "end".
>

nicer than:

(top-gdb) commands
Type commands for all specified breakpoints
End with a line saying just "end".
>

as in the latter case, I didn't specify any breakpoints, so
"specified breakpoints" sounds vague, and doesn't quickly
imply that it will create commands for all previously created
breakpoints.

> * NEWS: Mention changes to `commands' and `rbreak'.
> * gdb.texinfo (Break Commands): Update.

I'm also suggesting to adjusting these to better explain that
this applies when "break" (or similars) creates more than one
breakpoint. That is different to creating a breakpoint with
multiple locations ("multiple locations" are described both
in the manual and in NEWS); in the multiple locations case,
"commands" already applied to all locations. I'm adding
a cross reference to where the case where multiple breakpoints
are created is described; that section has a nice example.

WDYT?

--
Pedro Alves

2010-03-25 Pedro Alves <pedro@codesourcery.com>

gdb/
* breakpoint.c (multi_start, multi_end, last_was_multi): Delete.
(prev_breakpoint_count): New.
(set_breakpoint_count): Adjust.
(rbreak_start_breakpoint_count): New.
(start_rbreak_breakpoints): Adjust.
(end_rbreak_breakpoints): Adjust.
(struct commands_info) <arg>: New field.
(do_map_commands_command): Tweak output to include breakpoint spec
range.
(commands_command_1): Adjust. Avoid setting an xfree cleanup if
ARG was empty on entry. Set INFO's arg.
(create_breakpoint): Adjust.

* NEWS: Clarify `commands' changes.

gdb/doc/
* gdb.texinfo (Break Commands): Clarify `commands' changes, and
add cross reference.

gdb/testsuite/
* gdb.base/commands.exp: Adjust.
* gdb.cp/extern-c.exp: Adjust.

---
gdb/NEWS | 7 ++-
gdb/breakpoint.c | 72 +++++++++++++++++++++++-------------
gdb/doc/gdb.texinfo | 5 +-
gdb/testsuite/gdb.base/commands.exp | 6 +--
gdb/testsuite/gdb.cp/extern-c.exp | 2 -
5 files changed, 58 insertions(+), 34 deletions(-)

Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c 2010-03-25 14:50:13.000000000 +0000
+++ src/gdb/breakpoint.c 2010-03-25 16:43:09.000000000 +0000
@@ -390,13 +390,11 @@ VEC(bp_location_p) *moribund_locations =

static int breakpoint_count;

-/* If the last command to create a breakpoint created multiple
- breakpoints, this holds the start and end breakpoint numbers. */
-static int multi_start;
-static int multi_end;
-/* True if the last breakpoint set was part of a group set with a
- single command, e.g., "rbreak". */
-static int last_was_multi;
+/* The value of `breakpoint_count' before the last command that
+ created breakpoints. If the last (break-like) command created more
+ than one breakpoint, then the difference between BREAKPOINT_COUNT
+ and PREV_BREAKPOINT_COUNT is more than one. */
+static int prev_breakpoint_count;

/* Number of last tracepoint made. */

@@ -414,29 +412,31 @@ breakpoint_enabled (struct breakpoint *b
static void
set_breakpoint_count (int num)
{
+ prev_breakpoint_count = breakpoint_count;
breakpoint_count = num;
- last_was_multi = 0;
set_internalvar_integer (lookup_internalvar ("bpnum"), num);
}

+/* Used by `start_rbreak_breakpoints' below, to record the current
+ breakpoint count before "rbreak" creates any breakpoint. */
+static int rbreak_start_breakpoint_count;
+
/* Called at the start an "rbreak" command to record the first
breakpoint made. */
+
void
start_rbreak_breakpoints (void)
{
- multi_start = breakpoint_count + 1;
+ rbreak_start_breakpoint_count = breakpoint_count;
}

/* Called at the end of an "rbreak" command to record the last
breakpoint made. */
+
void
end_rbreak_breakpoints (void)
{
- if (breakpoint_count >= multi_start)
- {
- multi_end = breakpoint_count;
- last_was_multi = 1;
- }
+ prev_breakpoint_count = rbreak_start_breakpoint_count;
}

/* Used in run_command to zero the hit count when a new run starts. */
@@ -896,9 +896,14 @@ struct commands_info
{
/* True if the command was typed at a tty. */
int from_tty;
+
+ /* The breakpoint range spec. */
+ char *arg;
+
/* Non-NULL if the body of the commands are being read from this
already-parsed command. */
struct command_line *control;
+
/* The command lines read from the user, or NULL if they have not
yet been read. */
struct counted_command_line *cmd;
@@ -919,12 +924,23 @@ do_map_commands_command (struct breakpoi
if (info->control != NULL)
l = copy_command_lines (info->control->body_list[0]);
else
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ str = xstrprintf (_("Type commands for breakpoint(s) %s, one per line."),
+ info->arg);
+
+ old_chain = make_cleanup (xfree, str);
+
+ l = read_command_lines (str,
+ info->from_tty, 1,
+ (breakpoint_is_tracepoint (b)
+ ? check_tracepoint_command : 0),
+ b);

- l = read_command_lines (_("Type commands for all specified breakpoints"),
- info->from_tty, 1,
- (breakpoint_is_tracepoint (b)
- ? check_tracepoint_command : 0),
- b);
+ do_cleanups (old_chain);
+ }

info->cmd = alloc_counted_command_line (l);
}
@@ -957,13 +973,19 @@ commands_command_1 (char *arg, int from_

if (arg == NULL || !*arg)
{
- if (last_was_multi)
- arg = xstrprintf ("%d-%d", multi_start, multi_end);
+ if (breakpoint_count - prev_breakpoint_count > 1)
+ arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, breakpoint_count);
else if (breakpoint_count > 0)
arg = xstrprintf ("%d", breakpoint_count);
- make_cleanup (xfree, arg);
+ else
+ arg = NULL;
+
+ if (arg != NULL)
+ make_cleanup (xfree, arg);
}

+ info.arg = arg;
+
map_breakpoint_numbers (arg, do_map_commands_command, &info);

if (info.cmd == NULL)
@@ -7176,7 +7198,7 @@ create_breakpoint (struct gdbarch *gdbar
int not_found = 0;
enum bptype type_wanted;
int task = 0;
- int first_bp_set = breakpoint_count + 1;
+ int prev_bkpt_count = breakpoint_count;

sals.sals = NULL;
sals.nelts = 0;
@@ -7336,9 +7358,7 @@ create_breakpoint (struct gdbarch *gdbar
{
warning (_("Multiple breakpoints were set.\n"
"Use the \"delete\" command to delete unwanted breakpoints."));
- multi_start = first_bp_set;
- multi_end = breakpoint_count;
- last_was_multi = 1;
+ prev_breakpoint_count = prev_bkpt_count;
}

/* That's it. Discard the cleanups for data inserted into the
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo 2010-03-25 15:45:15.000000000 +0000
+++ src/gdb/doc/gdb.texinfo 2010-03-25 16:54:03.000000000 +0000
@@ -4343,8 +4343,9 @@ watchpoint, or catchpoint set (not to th
encountered). If the most recent breakpoints were set with a single
command, then the @code{commands} will apply to all the breakpoints
set by that command. This applies to breakpoints set by
-@code{rbreak}, and also breakpoints set with @code{break} that have
-multiple locations.
+@code{rbreak}, and also applies when a single @code{break} command
+creates multiple breakpoints (@pxref{Ambiguous Expressions,,Ambiguous
+Expressions}).
@end table

Pressing @key{RET} as a means of repeating the last @value{GDBN} command is
Index: src/gdb/testsuite/gdb.base/commands.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.base/commands.exp 2010-03-25 16:07:22.000000000 +0000
+++ src/gdb/testsuite/gdb.base/commands.exp 2010-03-25 16:15:57.000000000 +0000
@@ -299,7 +299,7 @@ proc watchpoint_command_test {} {

send_gdb "commands $wp_id\n"
gdb_expect {
- -re "Type commands for all specified breakpoints.*>" {
+ -re "Type commands for breakpoint.*, one per line.*>" {
pass "begin commands on watch"
}
-re "$gdb_prompt $" {fail "begin commands on watch"}
@@ -452,7 +452,7 @@ proc bp_deleted_in_command_test {} {

send_gdb "commands\n"
gdb_expect {
- -re "Type commands for all specified breakpoints.*>" {
+ -re "Type commands for breakpoint.*>" {
pass "begin commands in bp_deleted_in_command_test"
}
-re "$gdb_prompt $" {fail "begin commands in bp_deleted_in_command_test"}
@@ -519,7 +519,7 @@ proc temporary_breakpoint_commands {} {

send_gdb "commands\n"
gdb_expect {
- -re "Type commands for all specified breakpoints.*>" {
+ -re "Type commands for breakpoint.*>" {
pass "begin commands in bp_deleted_in_command_test"
}
-re "$gdb_prompt $" {fail "begin commands in bp_deleted_in_command_test"}
Index: src/gdb/testsuite/gdb.cp/extern-c.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.cp/extern-c.exp 2010-03-25 16:07:33.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/extern-c.exp 2010-03-25 16:18:27.000000000 +0000
@@ -48,7 +48,7 @@ gdb_test "rbreak c_funcs" \
# Test that "commands" without an argument puts commands on both
# breakpoints.
gdb_test_multiple "commands" "set commands on multiple breakpoints" {
- -re "Type commands for all specified breakpoints\r\nEnd with a line saying just \"end\".\r\n>$" {
+ -re "Type commands for breakpoint\\(s\\) 3-4, one per line\.\r\nEnd with a line saying just \"end\".\r\n>$" {
gdb_test_multiple "set \$counter = \$counter + 1\nend" \
"command details for multiple breakpoints" {
-re "$gdb_prompt $" {
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS 2010-03-25 16:44:23.000000000 +0000
+++ src/gdb/NEWS 2010-03-25 16:52:29.000000000 +0000
@@ -14,8 +14,11 @@
register EAX or 64-bit register RAX.

* The `commands' command now accepts a range of breakpoints to modify.
- A plain `commands' following an `rbreak' will affect all the
- breakpoints set by `rbreak'.
+ A plain `commands' following a command that creates multiple
+ breakpoints affects all the breakpoints set by that command. This
+ applies to breakpoints set by `rbreak', and also applies when a
+ single `break' command creates multiple breakpoints (e.g.,
+ breakpoints on overloaded c++ functions).

* Python scripting