* [RFA] Implement -break-commands
@ 2009-07-27 16:00 Vladimir Prus
2009-07-27 16:08 ` Marc Khouzam
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Vladimir Prus @ 2009-07-27 16:00 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: Text/Plain, Size: 801 bytes --]
The below patches implement MI -break-commands. As the name implies,
it's the same as CLI 'commands'. There are two patches: one
refactors CLI 'commands' for easier reuse, and the second actually
adds -break-commands. The patches mostly were derived from Apple
branch, and then adjusted for CVS HEAD. One functional change I've
made is that '-break-commands <number>' does not report the list
of currently set commands -- since -break-info already prints his
information, it does not seem necessary to add another way. I've
also added a test and docs.
The parts of this patch that are not MI are:
1. Slight refactoring of cli/cli-script.c
2. Slight refactoring of breakpoint.c
I'd appreciate if somebody could review them.
Eli, there's also doc change here, comments appreciated.
Thanks,
Volodya
[-- Attachment #2: 1.diff --]
[-- Type: text/x-patch, Size: 7345 bytes --]
commit 62615d166f3452572e17644d854285040d86bcdb
Author: Vladimir Prus <vladimir@codesourcery.com>
Date: Fri Jul 24 13:53:37 2009 +0400
Refactor reading of commands
2009-07-27 Jim Ingham <jingham@apple.com>
Vladimir Prus <vladimir@codesourcery.com>
* defs.h (read_command_lines_1): Declare.
* cli/cli-script.c (read_next_line): Only return string,
do not process.
(process_next_line): New, extracted from read_next_line.
(recurse_read_control_structure): Take a function pointer to the
read function.
(get_command_line) Pass the read_next_line as reader function
into recurse_read_control_structure.
(read_command_lines_1): New, extracted from...
(read_command_lines): ...here.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 054ce90..5478145 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -39,12 +39,15 @@
/* Prototypes for local functions */
static enum command_control_type
- recurse_read_control_structure (struct command_line *current_cmd);
+recurse_read_control_structure (char * (*read_next_line_func) (),
+ struct command_line *current_cmd);
static char *insert_args (char *line);
static struct cleanup * setup_user_args (char *p);
+static char *read_next_line ();
+
/* Level of control structure when reading. */
static int control_level;
@@ -114,7 +117,7 @@ get_command_line (enum command_control_type type, char *arg)
old_chain = make_cleanup_free_command_lines (&cmd);
/* Read in the body of this command. */
- if (recurse_read_control_structure (cmd) == invalid_control)
+ if (recurse_read_control_structure (read_next_line, cmd) == invalid_control)
{
warning (_("Error reading in canned sequence of commands."));
do_cleanups (old_chain);
@@ -837,19 +840,12 @@ realloc_body_list (struct command_line *command, int new_length)
command->body_count = new_length;
}
-/* Read one line from the input stream. If the command is an "end",
- return such an indication to the caller. If PARSE_COMMANDS is true,
- strip leading whitespace (trailing whitespace is always stripped)
- in the line, attempt to recognize GDB control commands, and also
- return an indication if the command is an "else" or a nop.
- Otherwise, only "end" is recognized. */
-static enum misc_command_type
-read_next_line (struct command_line **command, int parse_commands)
+char *
+read_next_line ()
{
- char *p, *p1, *prompt_ptr, control_prompt[256];
+ char *prompt_ptr, control_prompt[256];
int i = 0;
- int not_handled = 0;
if (control_level >= 254)
error (_("Control nesting too deep!"));
@@ -866,7 +862,21 @@ read_next_line (struct command_line **command, int parse_commands)
else
prompt_ptr = NULL;
- p = command_line_input (prompt_ptr, instream == stdin, "commands");
+ return command_line_input (prompt_ptr, instream == stdin, "commands");
+}
+
+/* Process one input line. If the command is an "end",
+ return such an indication to the caller. If PARSE_COMMANDS is true,
+ strip leading whitespace (trailing whitespace is always stripped)
+ in the line, attempt to recognize GDB control commands, and also
+ return an indication if the command is an "else" or a nop.
+ Otherwise, only "end" is recognized. */
+
+static enum misc_command_type
+process_next_line (char *p, struct command_line **command, int parse_commands)
+{
+ char *p1;
+ int not_handled = 0;
/* Not sure what to do here. */
if (p == NULL)
@@ -979,12 +989,14 @@ read_next_line (struct command_line **command, int parse_commands)
following commands are nested. */
static enum command_control_type
-recurse_read_control_structure (struct command_line *current_cmd)
+recurse_read_control_structure (char * (*read_next_line_func) (),
+ struct command_line *current_cmd)
{
int current_body, i;
enum misc_command_type val;
enum command_control_type ret;
struct command_line **body_ptr, *child_tail, *next;
+ char *p;
child_tail = NULL;
current_body = 1;
@@ -1002,7 +1014,8 @@ recurse_read_control_structure (struct command_line *current_cmd)
dont_repeat ();
next = NULL;
- val = read_next_line (&next, current_cmd->control_type != python_control);
+ val = process_next_line (read_next_line_func (), &next,
+ current_cmd->control_type != python_control);
/* Just skip blanks and comments. */
if (val == nop_command)
@@ -1068,7 +1081,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
|| next->control_type == commands_control)
{
control_level++;
- ret = recurse_read_control_structure (next);
+ ret = recurse_read_control_structure (read_next_line_func, next);
control_level--;
if (ret != simple_control)
@@ -1095,12 +1108,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
struct command_line *
read_command_lines (char *prompt_arg, int from_tty, int parse_commands)
{
- struct command_line *head, *tail, *next;
- struct cleanup *old_chain;
- enum command_control_type ret;
- enum misc_command_type val;
-
- control_level = 0;
+ struct command_line *head;
if (from_tty && input_from_terminal_p ())
{
@@ -1116,13 +1124,34 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands)
}
}
+ head = read_command_lines_1 (read_next_line, parse_commands);
+
+ if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
+ {
+ (*deprecated_readline_end_hook) ();
+ }
+ return (head);
+}
+
+/* Act the same way as read_command_lines, except that each new line is
+ obtained using READ_NEXT_LINE_FUNC. */
+
+struct command_line *
+read_command_lines_1 (char * (*read_next_line_func) (), int parse_commands)
+{
+ struct command_line *head, *tail, *next;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+ enum misc_command_type val;
+
+ control_level = 0;
head = tail = NULL;
old_chain = NULL;
while (1)
{
dont_repeat ();
- val = read_next_line (&next, parse_commands);
+ val = process_next_line (read_next_line_func (), &next, parse_commands);
/* Ignore blank lines or comments. */
if (val == nop_command)
@@ -1146,7 +1175,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands)
|| next->control_type == commands_control)
{
control_level++;
- ret = recurse_read_control_structure (next);
+ ret = recurse_read_control_structure (read_next_line_func, next);
control_level--;
if (ret == invalid_control)
@@ -1177,11 +1206,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands)
do_cleanups (old_chain);
}
- if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
- {
- (*deprecated_readline_end_hook) ();
- }
- return (head);
+ return head;
}
/* Free a chain of struct command_line's. */
diff --git a/gdb/defs.h b/gdb/defs.h
index 6dc5a6c..c1f8b60 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -696,6 +696,8 @@ struct command_line
};
extern struct command_line *read_command_lines (char *, int, int);
+extern struct command_line *read_command_lines_1
+(char * (*read_next_line_func) (), int parse_commands);
extern void free_command_lines (struct command_line **);
[-- Attachment #3: 2.diff --]
[-- Type: text/x-patch, Size: 10940 bytes --]
commit b3ee1c6c1c6c179c7ee652b5c591a5b07b80c46e
Author: Vladimir Prus <vladimir@codesourcery.com>
Date: Sat Jul 25 18:12:39 2009 +0400
Implement -break-commands
gdb/
2009-07-27 Jim Ingham <jingham@apple.com>
Vladimir Prus <vladimir@codesourcery.com>
* 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.
gdb/doc/
2009-07-27 Vladimir Prus <vladimir@codesourcery.com>
* gdb.texinfo (GDB/MI Breakpoint Commands): Document
-break-commands.
gdb/testsuite/
2009-07-27 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.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 3a18c8f..bb8c082 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -559,6 +559,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;
+}
\f
/* condition N EXP -- set break condition of breakpoint N to EXP. */
@@ -623,6 +637,16 @@ condition_command (char *arg, int from_tty)
error (_("No breakpoint number %d."), bnum);
}
+
+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)
{
@@ -652,10 +676,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);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 6731e68..54e2ea0 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -821,6 +821,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. */
@@ -836,6 +838,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);
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c3693fa..df0ffb6 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -21465,11 +21465,39 @@ 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}
+
+@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-command "print v" "continue"
+^done
+(gdb)
+@end smallexample
@subheading The @code{-break-condition} Command
@findex -break-condition
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index 445c53e..bb7ea14 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -252,3 +252,57 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
error (_("mi_cmd_break_watch: Unknown watchpoint type."));
}
}
+
+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);
+}
+
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 4911146..dd3d803 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -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 },
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index afcba1e..85ad0c4 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -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;
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index 4b8d101..619727d 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -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
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 9b4c464..e691232 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -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
^ permalink raw reply [flat|nested] 13+ messages in thread* RE: [RFA] Implement -break-commands 2009-07-27 16:00 [RFA] Implement -break-commands Vladimir Prus @ 2009-07-27 16:08 ` Marc Khouzam 2009-07-27 16:17 ` Vladimir Prus 2009-07-27 18:49 ` Tom Tromey 2009-07-27 18:56 ` Eli Zaretskii 2 siblings, 1 reply; 13+ messages in thread From: Marc Khouzam @ 2009-07-27 16:08 UTC (permalink / raw) To: Vladimir Prus, gdb-patches > -----Original Message----- > From: gdb-patches-owner@sourceware.org > [mailto:gdb-patches-owner@sourceware.org] On Behalf Of Vladimir Prus > Sent: Monday, July 27, 2009 5:03 AM > To: gdb-patches@sources.redhat.com > Subject: [RFA] Implement -break-commands > > > The below patches implement MI -break-commands. As the name implies, > it's the same as CLI 'commands'. There are two patches: one > refactors CLI 'commands' for easier reuse, and the second actually > adds -break-commands. The patches mostly were derived from Apple > branch, and then adjusted for CVS HEAD. One functional change I've > made is that '-break-commands <number>' does not report the list > of currently set commands -- since -break-info already prints his > information, it does not seem necessary to add another way. I've > also added a test and docs. Nice addition. > > The parts of this patch that are not MI are: > 1. Slight refactoring of cli/cli-script.c > 2. Slight refactoring of breakpoint.c > > I'd appreciate if somebody could review them. > > Eli, there's also doc change here, comments appreciated. I noticed the example in the doc is missing the breakpoint number: > +-break-command "print v" "continue" Unless it is optional? Marc ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 16:08 ` Marc Khouzam @ 2009-07-27 16:17 ` Vladimir Prus 0 siblings, 0 replies; 13+ messages in thread From: Vladimir Prus @ 2009-07-27 16:17 UTC (permalink / raw) To: Marc Khouzam; +Cc: gdb-patches On Monday 27 July 2009 Marc Khouzam wrote: > > -----Original Message----- > > From: gdb-patches-owner@sourceware.org > > [mailto:gdb-patches-owner@sourceware.org] On Behalf Of Vladimir Prus > > Sent: Monday, July 27, 2009 5:03 AM > > To: gdb-patches@sources.redhat.com > > Subject: [RFA] Implement -break-commands > > > > > > The below patches implement MI -break-commands. As the name implies, > > it's the same as CLI 'commands'. There are two patches: one > > refactors CLI 'commands' for easier reuse, and the second actually > > adds -break-commands. The patches mostly were derived from Apple > > branch, and then adjusted for CVS HEAD. One functional change I've > > made is that '-break-commands <number>' does not report the list > > of currently set commands -- since -break-info already prints his > > information, it does not seem necessary to add another way. I've > > also added a test and docs. > > Nice addition. > > > > > The parts of this patch that are not MI are: > > 1. Slight refactoring of cli/cli-script.c > > 2. Slight refactoring of breakpoint.c > > > > I'd appreciate if somebody could review them. > > > > Eli, there's also doc change here, comments appreciated. > > I noticed the example in the doc is missing the breakpoint number: > > > +-break-command "print v" "continue" > > Unless it is optional? It's a doc bug -- thanks for noticing. I've fixed it in my patch tree. - Volodya ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 16:00 [RFA] Implement -break-commands Vladimir Prus 2009-07-27 16:08 ` Marc Khouzam @ 2009-07-27 18:49 ` Tom Tromey 2009-07-27 17:38 ` Vladimir Prus 2009-07-30 7:54 ` Vladimir Prus 2009-07-27 18:56 ` Eli Zaretskii 2 siblings, 2 replies; 13+ messages in thread From: Tom Tromey @ 2009-07-27 18:49 UTC (permalink / raw) To: Vladimir Prus; +Cc: gdb-patches >>>>> "Volodya" == Vladimir Prus <vladimir@codesourcery.com> writes: This all looks reasonable to me. I have a few style nits. Volodya> -/* Read one line from the input stream. If the command is an "end", Volodya> - return such an indication to the caller. If PARSE_COMMANDS is true, Volodya> - strip leading whitespace (trailing whitespace is always stripped) Volodya> - in the line, attempt to recognize GDB control commands, and also Volodya> - return an indication if the command is an "else" or a nop. Volodya> - Otherwise, only "end" is recognized. */ Volodya> -static enum misc_command_type Volodya> -read_next_line (struct command_line **command, int parse_commands) Volodya> +char * Volodya> +read_next_line () This should be marked `static' (it is declared that way but it is clearer to mark the definition as well). I think it needs a header comment. Volodya> static enum command_control_type Volodya> -recurse_read_control_structure (struct command_line *current_cmd) Volodya> +recurse_read_control_structure (char * (*read_next_line_func) (), Volodya> + struct command_line *current_cmd) The header comment should be updated to mention the new argument. And if you don't mind, please fix the reference to the non-existing "parent_control" parameter. Volodya> +extern struct command_line *read_command_lines_1 Volodya> +(char * (*read_next_line_func) (), int parse_commands); Indentation on the 2nd line. There's some other little style nits in the patch -- over-bracing in the second patch, mostly. Volodya> +void Volodya> +breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) Needs a header comment. Volodya> +static char **mi_command_line_array; Volodya> +static int mi_command_line_array_cnt; Volodya> +static int mi_command_line_array_ptr; [...] Volodya> + break_command = read_command_lines_1 (mi_read_next_line, 0); I think this would be cleaner if read_command_lines_1 took a "user_data" argument and then there were no new globals. Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 18:49 ` Tom Tromey @ 2009-07-27 17:38 ` Vladimir Prus 2009-07-29 21:08 ` Tom Tromey 2009-07-30 7:54 ` Vladimir Prus 1 sibling, 1 reply; 13+ messages in thread From: Vladimir Prus @ 2009-07-27 17:38 UTC (permalink / raw) To: tromey; +Cc: gdb-patches On Monday 27 July 2009 Tom Tromey wrote: > >>>>> "Volodya" == Vladimir Prus <vladimir@codesourcery.com> writes: > > This all looks reasonable to me. I have a few style nits. > > Volodya> -/* Read one line from the input stream. If the command is an "end", > Volodya> - return such an indication to the caller. If PARSE_COMMANDS is true, > Volodya> - strip leading whitespace (trailing whitespace is always stripped) > Volodya> - in the line, attempt to recognize GDB control commands, and also > Volodya> - return an indication if the command is an "else" or a nop. > Volodya> - Otherwise, only "end" is recognized. */ > > Volodya> -static enum misc_command_type > Volodya> -read_next_line (struct command_line **command, int parse_commands) > Volodya> +char * > Volodya> +read_next_line () > > This should be marked `static' (it is declared that way but it is > clearer to mark the definition as well). I think it needs a header > comment. > > Volodya> static enum command_control_type > Volodya> -recurse_read_control_structure (struct command_line *current_cmd) > Volodya> +recurse_read_control_structure (char * (*read_next_line_func) (), > Volodya> + struct command_line *current_cmd) > > The header comment should be updated to mention the new argument. > And if you don't mind, please fix the reference to the non-existing > "parent_control" parameter. > > Volodya> +extern struct command_line *read_command_lines_1 > Volodya> +(char * (*read_next_line_func) (), int parse_commands); > > Indentation on the 2nd line. > > There's some other little style nits in the patch -- over-bracing in the > second patch, mostly. Is that something you want fixed? I do prefer bracing everything, since that is safer in the long run. > > Volodya> +void > Volodya> +breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) > > Needs a header comment. Do we have a policy if function should be documented in header, or implementation? It seems many existing files have comments on implementation. > Volodya> +static char **mi_command_line_array; > Volodya> +static int mi_command_line_array_cnt; > Volodya> +static int mi_command_line_array_ptr; > > [...] > > Volodya> + break_command = read_command_lines_1 (mi_read_next_line, 0); > > I think this would be cleaner if read_command_lines_1 took a "user_data" > argument and then there were no new globals. It would be clearer, though I decided not to do that because it's not likely we'll need another such function, and the use of globals in this context is ugly, but safe. Shall I refactor? Thanks, Volodya ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 17:38 ` Vladimir Prus @ 2009-07-29 21:08 ` Tom Tromey 0 siblings, 0 replies; 13+ messages in thread From: Tom Tromey @ 2009-07-29 21:08 UTC (permalink / raw) To: Vladimir Prus; +Cc: gdb-patches Tom> There's some other little style nits in the patch -- over-bracing Tom> in the second patch, mostly. Volodya> Is that something you want fixed? I do prefer bracing Volodya> everything, since that is safer in the long run. Yes, please fix this. AFAIK this is the documented style. Volodya> +void Volodya> +breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) Tom> Needs a header comment. Volodya> Do we have a policy if function should be documented in header, Volodya> or implementation? It seems many existing files have comments Volodya> on implementation. It is hard to say whether we arrived at a policy the last time we had this discussion. These things rarely seem to converge, they just wander off into the weeds. I usually follow the prevailing style of the module I am modifying. That is always a safe thing to do. Tom> I think this would be cleaner if read_command_lines_1 took a "user_data" Tom> argument and then there were no new globals. Volodya> It would be clearer, though I decided not to do that because Volodya> it's not likely we'll need another such function, and the use Volodya> of globals in this context is ugly, but safe. Shall I refactor? This one is up to you :-) Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 18:49 ` Tom Tromey 2009-07-27 17:38 ` Vladimir Prus @ 2009-07-30 7:54 ` Vladimir Prus 2009-07-30 16:57 ` Tom Tromey 2009-07-30 21:22 ` Eli Zaretskii 1 sibling, 2 replies; 13+ messages in thread From: Vladimir Prus @ 2009-07-30 7:54 UTC (permalink / raw) To: tromey; +Cc: gdb-patches [-- Attachment #1: Type: Text/Plain, Size: 2411 bytes --] On Monday 27 July 2009 Tom Tromey wrote: > >>>>> "Volodya" == Vladimir Prus <vladimir@codesourcery.com> writes: > > This all looks reasonable to me. I have a few style nits. > > Volodya> -/* Read one line from the input stream. If the command is an "end", > Volodya> - return such an indication to the caller. If PARSE_COMMANDS is true, > Volodya> - strip leading whitespace (trailing whitespace is always stripped) > Volodya> - in the line, attempt to recognize GDB control commands, and also > Volodya> - return an indication if the command is an "else" or a nop. > Volodya> - Otherwise, only "end" is recognized. */ > > Volodya> -static enum misc_command_type > Volodya> -read_next_line (struct command_line **command, int parse_commands) > Volodya> +char * > Volodya> +read_next_line () > > This should be marked `static' (it is declared that way but it is > clearer to mark the definition as well). I think it needs a header > comment. > > Volodya> static enum command_control_type > Volodya> -recurse_read_control_structure (struct command_line *current_cmd) > Volodya> +recurse_read_control_structure (char * (*read_next_line_func) (), > Volodya> + struct command_line *current_cmd) > > The header comment should be updated to mention the new argument. > And if you don't mind, please fix the reference to the non-existing > "parent_control" parameter. > > Volodya> +extern struct command_line *read_command_lines_1 > Volodya> +(char * (*read_next_line_func) (), int parse_commands); > > Indentation on the 2nd line. > > There's some other little style nits in the patch -- over-bracing in the > second patch, mostly. > > Volodya> +void > Volodya> +breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) > > Needs a header comment. > > Volodya> +static char **mi_command_line_array; > Volodya> +static int mi_command_line_array_cnt; > Volodya> +static int mi_command_line_array_ptr; > > [...] > > Volodya> + break_command = read_command_lines_1 (mi_read_next_line, 0); > > I think this would be cleaner if read_command_lines_1 took a "user_data" > argument and then there were no new globals. This revision addresses all the comments above, except that request for 'closure' pointer to read_command_lines_1 if addressed by a comment saying why we don't do that. Eli, I've also applied your documentation suggestions. Is this OK? - Volodya [-- Attachment #2: 1.diff --] [-- Type: text/x-patch, Size: 7583 bytes --] commit 51e2d6c76a2fa48b1eb0a4f7c9af87789fe45a26 Author: Vladimir Prus <vladimir@codesourcery.com> Date: Fri Jul 24 13:53:37 2009 +0400 Refactor reading of commands 2009-07-27 Jim Ingham <jingham@apple.com> Vladimir Prus <vladimir@codesourcery.com> * defs.h (read_command_lines_1): Declare. * cli/cli-script.c (read_next_line): Only return string, do not process. (process_next_line): New, extracted from read_next_line. (recurse_read_control_structure): Take a function pointer to the read function. (get_command_line) Pass the read_next_line as reader function into recurse_read_control_structure. (read_command_lines_1): New, extracted from... (read_command_lines): ...here. diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 054ce90..62c4f24 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -39,12 +39,15 @@ /* Prototypes for local functions */ static enum command_control_type - recurse_read_control_structure (struct command_line *current_cmd); +recurse_read_control_structure (char * (*read_next_line_func) (), + struct command_line *current_cmd); static char *insert_args (char *line); static struct cleanup * setup_user_args (char *p); +static char *read_next_line (); + /* Level of control structure when reading. */ static int control_level; @@ -114,7 +117,7 @@ get_command_line (enum command_control_type type, char *arg) old_chain = make_cleanup_free_command_lines (&cmd); /* Read in the body of this command. */ - if (recurse_read_control_structure (cmd) == invalid_control) + if (recurse_read_control_structure (read_next_line, cmd) == invalid_control) { warning (_("Error reading in canned sequence of commands.")); do_cleanups (old_chain); @@ -837,19 +840,12 @@ realloc_body_list (struct command_line *command, int new_length) command->body_count = new_length; } -/* Read one line from the input stream. If the command is an "end", - return such an indication to the caller. If PARSE_COMMANDS is true, - strip leading whitespace (trailing whitespace is always stripped) - in the line, attempt to recognize GDB control commands, and also - return an indication if the command is an "else" or a nop. - Otherwise, only "end" is recognized. */ -static enum misc_command_type -read_next_line (struct command_line **command, int parse_commands) +static char * +read_next_line () { - char *p, *p1, *prompt_ptr, control_prompt[256]; + char *prompt_ptr, control_prompt[256]; int i = 0; - int not_handled = 0; if (control_level >= 254) error (_("Control nesting too deep!")); @@ -866,7 +862,21 @@ read_next_line (struct command_line **command, int parse_commands) else prompt_ptr = NULL; - p = command_line_input (prompt_ptr, instream == stdin, "commands"); + return command_line_input (prompt_ptr, instream == stdin, "commands"); +} + +/* Process one input line. If the command is an "end", + return such an indication to the caller. If PARSE_COMMANDS is true, + strip leading whitespace (trailing whitespace is always stripped) + in the line, attempt to recognize GDB control commands, and also + return an indication if the command is an "else" or a nop. + Otherwise, only "end" is recognized. */ + +static enum misc_command_type +process_next_line (char *p, struct command_line **command, int parse_commands) +{ + char *p1; + int not_handled = 0; /* Not sure what to do here. */ if (p == NULL) @@ -973,18 +983,20 @@ read_next_line (struct command_line **command, int parse_commands) } /* Recursively read in the control structures and create a command_line - structure from them. + structure from them. Use read_next_line_func to obtain lines of + the command. - The parent_control parameter is the control structure in which the - following commands are nested. */ +*/ static enum command_control_type -recurse_read_control_structure (struct command_line *current_cmd) +recurse_read_control_structure (char * (*read_next_line_func) (), + struct command_line *current_cmd) { int current_body, i; enum misc_command_type val; enum command_control_type ret; struct command_line **body_ptr, *child_tail, *next; + char *p; child_tail = NULL; current_body = 1; @@ -1002,7 +1014,8 @@ recurse_read_control_structure (struct command_line *current_cmd) dont_repeat (); next = NULL; - val = read_next_line (&next, current_cmd->control_type != python_control); + val = process_next_line (read_next_line_func (), &next, + current_cmd->control_type != python_control); /* Just skip blanks and comments. */ if (val == nop_command) @@ -1068,7 +1081,7 @@ recurse_read_control_structure (struct command_line *current_cmd) || next->control_type == commands_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next); control_level--; if (ret != simple_control) @@ -1095,12 +1108,7 @@ recurse_read_control_structure (struct command_line *current_cmd) struct command_line * read_command_lines (char *prompt_arg, int from_tty, int parse_commands) { - struct command_line *head, *tail, *next; - struct cleanup *old_chain; - enum command_control_type ret; - enum misc_command_type val; - - control_level = 0; + struct command_line *head; if (from_tty && input_from_terminal_p ()) { @@ -1116,13 +1124,34 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) } } + head = read_command_lines_1 (read_next_line, parse_commands); + + if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) + { + (*deprecated_readline_end_hook) (); + } + return (head); +} + +/* Act the same way as read_command_lines, except that each new line is + obtained using READ_NEXT_LINE_FUNC. */ + +struct command_line * +read_command_lines_1 (char * (*read_next_line_func) (), int parse_commands) +{ + struct command_line *head, *tail, *next; + struct cleanup *old_chain; + enum command_control_type ret; + enum misc_command_type val; + + control_level = 0; head = tail = NULL; old_chain = NULL; while (1) { dont_repeat (); - val = read_next_line (&next, parse_commands); + val = process_next_line (read_next_line_func (), &next, parse_commands); /* Ignore blank lines or comments. */ if (val == nop_command) @@ -1146,7 +1175,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) || next->control_type == commands_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next); control_level--; if (ret == invalid_control) @@ -1177,11 +1206,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) do_cleanups (old_chain); } - if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) - { - (*deprecated_readline_end_hook) (); - } - return (head); + return head; } /* Free a chain of struct command_line's. */ diff --git a/gdb/defs.h b/gdb/defs.h index 6dc5a6c..f5127fd 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -696,6 +696,7 @@ struct command_line }; extern struct command_line *read_command_lines (char *, int, int); +extern struct command_line *read_command_lines_1 (char * (*) (), int); extern void free_command_lines (struct command_line **); [-- Attachment #3: 2.diff --] [-- Type: text/x-patch, Size: 11343 bytes --] commit da96c898c51d51be3486026114752970b6092fb8 Author: Vladimir Prus <vladimir@codesourcery.com> Date: Sat Jul 25 18:12:39 2009 +0400 Implement -break-commands gdb/ 2009-07-27 Jim Ingham <jingham@apple.com> Vladimir Prus <vladimir@codesourcery.com> * 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. gdb/doc/ 2009-07-27 Vladimir Prus <vladimir@codesourcery.com> * gdb.texinfo (GDB/MI Breakpoint Commands): Document -break-commands. gdb/testsuite/ 2009-07-27 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. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3a18c8f..4b9b44e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -559,6 +559,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; +} \f /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -623,6 +637,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) { @@ -652,10 +677,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); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 6731e68..54e2ea0 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -821,6 +821,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. */ @@ -836,6 +838,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); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c3693fa..f598ebe 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -21465,11 +21465,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 diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 445c53e..9ab8f2d 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -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); +} + diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 4911146..dd3d803 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -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 }, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index afcba1e..85ad0c4 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -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; diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp index 4b8d101..619727d 100644 --- a/gdb/testsuite/gdb.mi/mi-break.exp +++ b/gdb/testsuite/gdb.mi/mi-break.exp @@ -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 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 9b4c464..e691232 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-30 7:54 ` Vladimir Prus @ 2009-07-30 16:57 ` Tom Tromey 2009-08-03 12:40 ` Vladimir Prus 2009-07-30 21:22 ` Eli Zaretskii 1 sibling, 1 reply; 13+ messages in thread From: Tom Tromey @ 2009-07-30 16:57 UTC (permalink / raw) To: Vladimir Prus; +Cc: gdb-patches >>>>> "Volodya" == Vladimir Prus <vladimir@codesourcery.com> writes: Volodya> This revision addresses all the comments above, except that Volodya> request for 'closure' pointer to read_command_lines_1 if Volodya> addressed by a comment saying why we don't do that. There still isn't a header comment on read_next_line. Just something like "helper function for use with recurse_read_control_structure" would be fine. This is ok with the addition of a comment. thanks, Tom ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-30 16:57 ` Tom Tromey @ 2009-08-03 12:40 ` Vladimir Prus 0 siblings, 0 replies; 13+ messages in thread From: Vladimir Prus @ 2009-08-03 12:40 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: Text/Plain, Size: 588 bytes --] On Thursday 30 July 2009 Tom Tromey wrote: > >>>>> "Volodya" == Vladimir Prus <vladimir@codesourcery.com> writes: > > Volodya> This revision addresses all the comments above, except that > Volodya> request for 'closure' pointer to read_command_lines_1 if > Volodya> addressed by a comment saying why we don't do that. > > There still isn't a header comment on read_next_line. Just something > like "helper function for use with recurse_read_control_structure" would > be fine. This is ok with the addition of a comment. Thanks. Checked in with that change, see attached. - Volodya [-- Attachment #2: a.diff --] [-- Type: text/x-patch, Size: 7740 bytes --] commit f4dc5936f411766cf8679d752e416e8644caafc8 Author: Vladimir Prus <vladimir@codesourcery.com> Date: Fri Jul 24 13:53:37 2009 +0400 Refactor reading of commands 2009-07-27 Jim Ingham <jingham@apple.com> Vladimir Prus <vladimir@codesourcery.com> * defs.h (read_command_lines_1): Declare. * cli/cli-script.c (read_next_line): Only return string, do not process. (process_next_line): New, extracted from read_next_line. (recurse_read_control_structure): Take a function pointer to the read function. (get_command_line) Pass the read_next_line as reader function into recurse_read_control_structure. (read_command_lines_1): New, extracted from... (read_command_lines): ...here. diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 054ce90..6e90bf2 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -39,12 +39,15 @@ /* Prototypes for local functions */ static enum command_control_type - recurse_read_control_structure (struct command_line *current_cmd); +recurse_read_control_structure (char * (*read_next_line_func) (), + struct command_line *current_cmd); static char *insert_args (char *line); static struct cleanup * setup_user_args (char *p); +static char *read_next_line (); + /* Level of control structure when reading. */ static int control_level; @@ -114,7 +117,7 @@ get_command_line (enum command_control_type type, char *arg) old_chain = make_cleanup_free_command_lines (&cmd); /* Read in the body of this command. */ - if (recurse_read_control_structure (cmd) == invalid_control) + if (recurse_read_control_structure (read_next_line, cmd) == invalid_control) { warning (_("Error reading in canned sequence of commands.")); do_cleanups (old_chain); @@ -837,19 +840,15 @@ realloc_body_list (struct command_line *command, int new_length) command->body_count = new_length; } -/* Read one line from the input stream. If the command is an "end", - return such an indication to the caller. If PARSE_COMMANDS is true, - strip leading whitespace (trailing whitespace is always stripped) - in the line, attempt to recognize GDB control commands, and also - return an indication if the command is an "else" or a nop. - Otherwise, only "end" is recognized. */ +/* Read next line from stdout. Passed to read_command_line_1 and + recurse_read_control_structure whenever we need to read commands + from stdout. */ -static enum misc_command_type -read_next_line (struct command_line **command, int parse_commands) +static char * +read_next_line () { - char *p, *p1, *prompt_ptr, control_prompt[256]; + char *prompt_ptr, control_prompt[256]; int i = 0; - int not_handled = 0; if (control_level >= 254) error (_("Control nesting too deep!")); @@ -866,7 +865,21 @@ read_next_line (struct command_line **command, int parse_commands) else prompt_ptr = NULL; - p = command_line_input (prompt_ptr, instream == stdin, "commands"); + return command_line_input (prompt_ptr, instream == stdin, "commands"); +} + +/* Process one input line. If the command is an "end", + return such an indication to the caller. If PARSE_COMMANDS is true, + strip leading whitespace (trailing whitespace is always stripped) + in the line, attempt to recognize GDB control commands, and also + return an indication if the command is an "else" or a nop. + Otherwise, only "end" is recognized. */ + +static enum misc_command_type +process_next_line (char *p, struct command_line **command, int parse_commands) +{ + char *p1; + int not_handled = 0; /* Not sure what to do here. */ if (p == NULL) @@ -973,18 +986,20 @@ read_next_line (struct command_line **command, int parse_commands) } /* Recursively read in the control structures and create a command_line - structure from them. + structure from them. Use read_next_line_func to obtain lines of + the command. - The parent_control parameter is the control structure in which the - following commands are nested. */ +*/ static enum command_control_type -recurse_read_control_structure (struct command_line *current_cmd) +recurse_read_control_structure (char * (*read_next_line_func) (), + struct command_line *current_cmd) { int current_body, i; enum misc_command_type val; enum command_control_type ret; struct command_line **body_ptr, *child_tail, *next; + char *p; child_tail = NULL; current_body = 1; @@ -1002,7 +1017,8 @@ recurse_read_control_structure (struct command_line *current_cmd) dont_repeat (); next = NULL; - val = read_next_line (&next, current_cmd->control_type != python_control); + val = process_next_line (read_next_line_func (), &next, + current_cmd->control_type != python_control); /* Just skip blanks and comments. */ if (val == nop_command) @@ -1068,7 +1084,7 @@ recurse_read_control_structure (struct command_line *current_cmd) || next->control_type == commands_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next); control_level--; if (ret != simple_control) @@ -1095,12 +1111,7 @@ recurse_read_control_structure (struct command_line *current_cmd) struct command_line * read_command_lines (char *prompt_arg, int from_tty, int parse_commands) { - struct command_line *head, *tail, *next; - struct cleanup *old_chain; - enum command_control_type ret; - enum misc_command_type val; - - control_level = 0; + struct command_line *head; if (from_tty && input_from_terminal_p ()) { @@ -1116,13 +1127,34 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) } } + head = read_command_lines_1 (read_next_line, parse_commands); + + if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) + { + (*deprecated_readline_end_hook) (); + } + return (head); +} + +/* Act the same way as read_command_lines, except that each new line is + obtained using READ_NEXT_LINE_FUNC. */ + +struct command_line * +read_command_lines_1 (char * (*read_next_line_func) (), int parse_commands) +{ + struct command_line *head, *tail, *next; + struct cleanup *old_chain; + enum command_control_type ret; + enum misc_command_type val; + + control_level = 0; head = tail = NULL; old_chain = NULL; while (1) { dont_repeat (); - val = read_next_line (&next, parse_commands); + val = process_next_line (read_next_line_func (), &next, parse_commands); /* Ignore blank lines or comments. */ if (val == nop_command) @@ -1146,7 +1178,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) || next->control_type == commands_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next); control_level--; if (ret == invalid_control) @@ -1177,11 +1209,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands) do_cleanups (old_chain); } - if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) - { - (*deprecated_readline_end_hook) (); - } - return (head); + return head; } /* Free a chain of struct command_line's. */ diff --git a/gdb/defs.h b/gdb/defs.h index 6dc5a6c..f5127fd 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -696,6 +696,7 @@ struct command_line }; extern struct command_line *read_command_lines (char *, int, int); +extern struct command_line *read_command_lines_1 (char * (*) (), int); extern void free_command_lines (struct command_line **); [-- Attachment #3: b.diff --] [-- Type: text/x-patch, Size: 11343 bytes --] commit dad2bfb291f5848c6da4260bf8adbc1086128ccf Author: Vladimir Prus <vladimir@codesourcery.com> Date: Sat Jul 25 18:12:39 2009 +0400 Implement -break-commands gdb/ 2009-07-27 Jim Ingham <jingham@apple.com> Vladimir Prus <vladimir@codesourcery.com> * 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. gdb/doc/ 2009-07-27 Vladimir Prus <vladimir@codesourcery.com> * gdb.texinfo (GDB/MI Breakpoint Commands): Document -break-commands. gdb/testsuite/ 2009-07-27 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. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3a18c8f..4b9b44e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -559,6 +559,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; +} \f /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -623,6 +637,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) { @@ -652,10 +677,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); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 6731e68..54e2ea0 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -821,6 +821,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. */ @@ -836,6 +838,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); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c3693fa..f598ebe 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -21465,11 +21465,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 diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 445c53e..9ab8f2d 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -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); +} + diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 4911146..dd3d803 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -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 }, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index afcba1e..85ad0c4 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -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; diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp index 4b8d101..619727d 100644 --- a/gdb/testsuite/gdb.mi/mi-break.exp +++ b/gdb/testsuite/gdb.mi/mi-break.exp @@ -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 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 9b4c464..e691232 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-30 7:54 ` Vladimir Prus 2009-07-30 16:57 ` Tom Tromey @ 2009-07-30 21:22 ` Eli Zaretskii 2009-08-03 12:42 ` Vladimir Prus 1 sibling, 1 reply; 13+ messages in thread From: Eli Zaretskii @ 2009-07-30 21:22 UTC (permalink / raw) To: Vladimir Prus; +Cc: tromey, gdb-patches > From: Vladimir Prus <vladimir@codesourcery.com> > Date: Thu, 30 Jul 2009 10:23:45 +0400 > Cc: gdb-patches@sources.redhat.com > > Eli, I've also applied your documentation suggestions. Is this OK? Yes, thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-30 21:22 ` Eli Zaretskii @ 2009-08-03 12:42 ` Vladimir Prus 2009-08-03 18:22 ` Eli Zaretskii 0 siblings, 1 reply; 13+ messages in thread From: Vladimir Prus @ 2009-08-03 12:42 UTC (permalink / raw) To: Eli Zaretskii; +Cc: tromey, gdb-patches On Thursday 30 July 2009 Eli Zaretskii wrote: > > From: Vladimir Prus <vladimir@codesourcery.com> > > Date: Thu, 30 Jul 2009 10:23:45 +0400 > > Cc: gdb-patches@sources.redhat.com > > > > Eli, I've also applied your documentation suggestions. Is this OK? > > Yes, thanks. I've just realized I failed to provide a patch for NEWS. What about the below? Thanks, Volodya --- gdb/NEWS 31 Jul 2009 15:35:37 -0000 1.324 +++ gdb/NEWS 3 Aug 2009 12:41:43 -0000 @@ -257,6 +257,9 @@ detach inferior NUM kill inferior NUM Kill inferior number NUM. +-break-commands + Set breakpoint commands using the GDB/MI interface + * New options set spu stop-on-load ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-08-03 12:42 ` Vladimir Prus @ 2009-08-03 18:22 ` Eli Zaretskii 0 siblings, 0 replies; 13+ messages in thread From: Eli Zaretskii @ 2009-08-03 18:22 UTC (permalink / raw) To: Vladimir Prus; +Cc: tromey, gdb-patches > From: Vladimir Prus <vladimir@codesourcery.com> > Date: Mon, 3 Aug 2009 16:42:31 +0400 > Cc: tromey@redhat.com, > gdb-patches@sources.redhat.com > > I've just realized I failed to provide a patch for NEWS. What about the > below? Yes, okay. But if other MI-related features are committed before the release, please make a new section for new MI features, and put this and the additional news there, so that all MI-related news are kept together. Thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFA] Implement -break-commands 2009-07-27 16:00 [RFA] Implement -break-commands Vladimir Prus 2009-07-27 16:08 ` Marc Khouzam 2009-07-27 18:49 ` Tom Tromey @ 2009-07-27 18:56 ` Eli Zaretskii 2 siblings, 0 replies; 13+ messages in thread From: Eli Zaretskii @ 2009-07-27 18:56 UTC (permalink / raw) To: Vladimir Prus; +Cc: gdb-patches > From: Vladimir Prus <vladimir@codesourcery.com> > Date: Mon, 27 Jul 2009 13:03:12 +0400 > > The below patches implement MI -break-commands. As the name implies, > it's the same as CLI 'commands'. Thanks. Could you perhaps say a few words about the use-cases where this is needed by a front end? > +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} Two spaces between sentences, please. > +-break-command "print v" "continue" "break-command" or "break-commands"? OK with those changes. How about a NEWS entry for this? ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2009-08-03 18:22 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-07-27 16:00 [RFA] Implement -break-commands Vladimir Prus 2009-07-27 16:08 ` Marc Khouzam 2009-07-27 16:17 ` Vladimir Prus 2009-07-27 18:49 ` Tom Tromey 2009-07-27 17:38 ` Vladimir Prus 2009-07-29 21:08 ` Tom Tromey 2009-07-30 7:54 ` Vladimir Prus 2009-07-30 16:57 ` Tom Tromey 2009-08-03 12:40 ` Vladimir Prus 2009-07-30 21:22 ` Eli Zaretskii 2009-08-03 12:42 ` Vladimir Prus 2009-08-03 18:22 ` Eli Zaretskii 2009-07-27 18:56 ` Eli Zaretskii
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox