Implement -break-commands
authorVladimir Prus <vladimir@codesourcery.com>
Mon, 3 Aug 2009 12:39:01 +0000 (12:39 +0000)
committerVladimir Prus <vladimir@codesourcery.com>
Mon, 3 Aug 2009 12:39:01 +0000 (12:39 +0000)
* 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/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/mi/mi-cmd-break.c
gdb/mi/mi-cmds.c
gdb/mi/mi-cmds.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-break.exp
gdb/testsuite/lib/mi-support.exp

index 57b8b9e2ea48536d4a02fe76d3964f6ea379b282..4bc40b4fbec68fe812b9ba9c7acb4ca1e3993a5c 100644 (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>
 
index 2e598e421eed2325af42de6eccda46c27b97609b..f3940e1f6425cc65183f3131088ea6a366158fd2 100644 (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;
+}
 
 \f
 /* 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);
index d8fe047c38baca17649a10242ffc46d57a94f8b4..d93c6b664abd6ff7fb927cca18e13465f781c2fa 100644 (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);
 
index dedf3fe11f4d8ca6dd1033cdf004dfa7d64985f5..91a5156498909ca095cf7faef31e06b5e7c549ab 100644 (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
index fab05fced0ebf40d6ed76a0283f99686ca289b50..f95e307d416f6d4c8f4dff8e8f6f423227db1e71 100644 (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
index 445c53ebeea40b725b5c19c295f01f8109d0b22b..9ab8f2df775ab3ba08ceef4fe584ea8168b78374 100644 (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);
+}
+
index 49111464b5cc7c4418386f001637bc254085913f..dd3d803851b2a927cb55b68340316f3f83b6cc89 100644 (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 },
index afcba1e4b42bee593a47cce54fad474e2534f5cf..85ad0c4c25b46b282171d9b73782d9ff4d325e46 100644 (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;
index d1e38f30ec2543843c12bfc9fbf6d0d1629bd525..32a421bcc9e6ddbbba4e9833e0672a5bb0a37258 100644 (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.
index 4b8d101b3a155370a77de54f4cfba99a259802a9..619727de24051b3ac3121376336eb8dbeefee994 100644 (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
index 9b4c464abcb1d9032857b0e84297bada84fe2dd0..e6912321d836c0681dcbd6c8bf0b3dba2996eaa7 100644 (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