Implement -break-commands

* breakpoint.c (get_breakpoint, breakpoint_set_commands): New.
	(commands_command): Use breakpoint_set_commands.
	* breakpoint.h (get_breakpoint, breakpoint_set_commands): Declare.

	* mi/mi-cmds.h (mi_cmd_break_commands): New.
	* mi/mi-cmds.c: Register -break-commands.
	* mi/mi-cmd-break.c (mi_cmd_break_commands, mi_read_next_line)
	(mi_command_line_array, mi_command_line_array_cnt)
	(mi_command_line_array_ptr): New.
This commit is contained in:
Vladimir Prus 2009-08-03 12:39:01 +00:00
parent 3c1179ff51
commit 48cb2d8581
11 changed files with 173 additions and 11 deletions

View file

@ -1,3 +1,18 @@
2009-08-03 Jim Ingham <jingham@apple.com>
Vladimir Prus <vladimir@codesourcery.com>
Implement -break-commands
* breakpoint.c (get_breakpoint, breakpoint_set_commands): New.
(commands_command): Use breakpoint_set_commands.
* breakpoint.h (get_breakpoint, breakpoint_set_commands): Declare.
* mi/mi-cmds.h (mi_cmd_break_commands): New.
* mi/mi-cmds.c: Register -break-commands.
* mi/mi-cmd-break.c (mi_cmd_break_commands, mi_read_next_line)
(mi_command_line_array, mi_command_line_array_cnt)
(mi_command_line_array_ptr): New.
2009-08-03 Jim Ingham <jingham@apple.com>
Vladimir Prus <vladimir@codesourcery.com>

View file

@ -562,6 +562,20 @@ get_number_or_range (char **pp)
return last_retval;
}
/* Return the breakpoint with the specified number, or NULL
if the number does not refer to an existing breakpoint. */
struct breakpoint *
get_breakpoint (int num)
{
struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->number == num)
return b;
return NULL;
}
/* condition N EXP -- set break condition of breakpoint N to EXP. */
@ -626,6 +640,17 @@ condition_command (char *arg, int from_tty)
error (_("No breakpoint number %d."), bnum);
}
/* Set the command list of B to COMMANDS. */
void
breakpoint_set_commands (struct breakpoint *b, struct command_line *commands)
{
free_command_lines (&b->commands);
b->commands = commands;
breakpoints_changed ();
observer_notify_breakpoint_modified (b->number);
}
static void
commands_command (char *arg, int from_tty)
{
@ -655,10 +680,7 @@ commands_command (char *arg, int from_tty)
struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
l = read_command_lines (tmpbuf, from_tty, 1);
do_cleanups (cleanups);
free_command_lines (&b->commands);
b->commands = l;
breakpoints_changed ();
observer_notify_breakpoint_modified (b->number);
breakpoint_set_commands (b, l);
return;
}
error (_("No breakpoint number %d."), bnum);

View file

@ -840,6 +840,8 @@ extern int get_number (char **);
extern int get_number_or_range (char **);
extern struct breakpoint *get_breakpoint (int num);
/* The following are for displays, which aren't really breakpoints, but
here is as good a place as any for them. */
@ -855,6 +857,9 @@ extern void disable_breakpoint (struct breakpoint *);
extern void enable_breakpoint (struct breakpoint *);
extern void breakpoint_set_commands (struct breakpoint *b,
struct command_line *commands);
/* Clear the "inserted" flag in all breakpoints. */
extern void mark_breakpoints_out (void);

View file

@ -1,3 +1,8 @@
2009-08-03 Vladimir Prus <vladimir@codesourcery.com>
* gdb.texinfo (GDB/MI Breakpoint Commands): Document
-break-commands.
2009-07-31 Ulrich Weigand <uweigand@de.ibm.com>
* gdb.texinfo (Cell Broadband Engine SPU architecture): Document the

View file

@ -21492,11 +21492,41 @@ line="5",times="0",ignore="3"@}]@}
@ignore
@subheading The @code{-break-catch} Command
@findex -break-catch
@end ignore
@subheading The @code{-break-commands} Command
@findex -break-commands
@end ignore
@subsubheading Synopsis
@smallexample
-break-commands @var{number} [ @var{command1} ... @var{commandN} ]
@end smallexample
Specifies the CLI commands that should be executed when breakpoint
@var{number} is hit. The parameters @var{command1} to @var{commandN}
are the commands. If no command is specified, any previously-set
commands are cleared. @xref{Break Commands}. Typical use of this
functionality is tracing a program, that is, printing of values of
some variables whenever breakpoint is hit and then continuing.
@subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{commands}.
@subsubheading Example
@smallexample
(gdb)
-break-insert main
^done,bkpt=@{number="1",type="breakpoint",disp="keep",
enabled="y",addr="0x000100d0",func="main",file="hello.c",
fullname="/home/foo/hello.c",line="5",times="0"@}
(gdb)
-break-commands 1 "print v" "continue"
^done
(gdb)
@end smallexample
@subheading The @code{-break-condition} Command
@findex -break-condition

View file

@ -252,3 +252,53 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
error (_("mi_cmd_break_watch: Unknown watchpoint type."));
}
}
/* The mi_read_next_line consults these variable to return successive
command lines. While it would be clearer to use a closure pointer,
it is not expected that any future code will use read_command_lines_1,
therefore no point of overengineering. */
static char **mi_command_line_array;
static int mi_command_line_array_cnt;
static int mi_command_line_array_ptr;
static char *
mi_read_next_line ()
{
if (mi_command_line_array_ptr == mi_command_line_array_cnt)
return NULL;
else
return mi_command_line_array[mi_command_line_array_ptr++];
}
void
mi_cmd_break_commands (char *command, char **argv, int argc)
{
struct command_line *break_command;
char *endptr;
int bnum;
struct breakpoint *b;
if (argc < 1)
error ("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]", command);
bnum = strtol (argv[0], &endptr, 0);
if (endptr == argv[0])
error ("breakpoint number argument \"%s\" is not a number.",
argv[0]);
else if (*endptr != '\0')
error ("junk at the end of breakpoint number argument \"%s\".",
argv[0]);
b = get_breakpoint (bnum);
if (b == NULL)
error ("breakpoint %d not found.", bnum);
mi_command_line_array = argv;
mi_command_line_array_ptr = 1;
mi_command_line_array_cnt = argc;
break_command = read_command_lines_1 (mi_read_next_line, 0);
breakpoint_set_commands (b, break_command);
}

View file

@ -35,6 +35,7 @@ struct mi_cmd mi_cmds[] =
{
{ "break-after", { "ignore", 1 }, NULL },
{ "break-condition", { "cond", 1 }, NULL },
{ "break-commands", { NULL, 0 }, mi_cmd_break_commands },
{ "break-delete", { "delete breakpoint", 1 }, NULL },
{ "break-disable", { "disable breakpoint", 1 }, NULL },
{ "break-enable", { "enable breakpoint", 1 }, NULL },

View file

@ -37,6 +37,7 @@ typedef void (mi_cmd_argv_ftype) (char *command, char **argv, int argc);
/* Function implementing each command */
extern mi_cmd_argv_ftype mi_cmd_break_insert;
extern mi_cmd_argv_ftype mi_cmd_break_commands;
extern mi_cmd_argv_ftype mi_cmd_break_watch;
extern mi_cmd_argv_ftype mi_cmd_disassemble;
extern mi_cmd_argv_ftype mi_cmd_data_evaluate_expression;

View file

@ -1,3 +1,9 @@
2009-08-03 Vladimir Prus <vladimir@codesourcery.com>
* lib/mi-support.exp (mi_list_breakpoints): Make it work.
* gdb.mi/mi-break.exp (test_breakpoint_commands): New.
Call it.
2009-07-31 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* configure.ac: Run gdb.cell tests when appropriate.

View file

@ -197,6 +197,30 @@ proc test_disabled_creation {} {
"test disabled creation: cleanup"
}
proc test_breakpoint_commands {} {
global line_callee2_body
global hex
global fullname
mi_create_breakpoint "basics.c:callee2" 7 keep callee2 ".*basics.c" $line_callee2_body $hex \
"breakpoint commands: insert breakpoint at basics.c:callee2"
mi_gdb_test "-break-commands 7 \"print 10\" \"continue\"" \
"\\^done" \
"breakpoint commands: set commands"
mi_gdb_test "-break-info 7" \
"\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"7\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"callee2\",file=\".*basics.c\",${fullname},line=\"$line_callee2_body\",times=\"0\",script=\{\"print 10\",\"continue\"\},original-location=\".*\"\}.*\\\]\}" \
"breakpoint commands: check that commands are set"
mi_gdb_test "-break-commands 7" \
"\\^done" \
"breakpoint commands: clear commands"
mi_list_breakpoints [list [list 7 "keep" "callee2" "basics.c" "$line_callee2_body" $hex]] \
"breakpoint commands: check that commands are cleared"
}
test_tbreak_creation_and_listing
test_rbreak_creation_and_listing
@ -206,5 +230,7 @@ test_error
test_disabled_creation
test_breakpoint_commands
mi_gdb_exit
return 0

View file

@ -1170,21 +1170,22 @@ proc mi_list_breakpoints { expected test } {
set body ""
set first 1
foreach item $children {
foreach item $expected {
if {$first == 0} {
set body "$body,"
set first 0
}
set number disp func file line address
set number [lindex $item 0]
set disp [lindex $item 1]
set func [lindex $item 2]
set line [lindex $item 3]
set address [lindex $item 4]
set body "$body,bkpt=\{number=\"$number\",type=\"breakpoint\",disp=\"$disp\",enabled=\"y\",addr=\"$address\",func=\"$func\",file=\"$file\",${fullname},line=\"$line\",times=\"0\",original-location=\".*\"\}"
set file [lindex $item 3]
set line [lindex $item 4]
set address [lindex $item 5]
set body "${body}bkpt=\{number=\"$number\",type=\"breakpoint\",disp=\"$disp\",enabled=\"y\",addr=\"$address\",func=\"$func\",file=\".*$file\",${fullname},line=\"$line\",times=\"0\",original-location=\".*\"\}"
set first 0
}
verbose -log "Expecint: 666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}" \
verbose -log "Expecting: 666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}"
mi_gdb_test "666-break-list" \
"666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}" \
$test