This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Breakpoint MI notifications


The enclosed patch implements MI notifications about breakpoint changes.
As other MI notifications, those are emitted only when breakpoint changes
by something that is not a MI command to change a breakpoint. For example,
-break-condition will not cause a breakpoint-changed notification to be
emitted.

This functionality was independently written by Tom and myself, and this
patch merges the patches together. As a side effect, existing breakpoint
observers were modified to take a pointer to breakpoint rather than it,
which eliminates quite some busywork.

Tested on x86 with no regressions. Comments?

- Volodya

-- 
Vladimir Prus
Mentor Graphics
+7 (812) 677-68-40
commit da3a2cbd2bf89cc495a2f848c6a8cac13a1af5c8
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Tue Apr 26 15:02:27 2011 +0400

        MI breakpoint notifications.
    
            * annotate.c (breakpoint_changed): Adjust parameter type.
            * breakpoint.c (set_breakpoint_condition): Adjust to change
            in breakpoint_modified type.
            (breakpoint_set_commands): Likewise.
            (do_map_commands_command): Likewise.
            (bpstat_check_breakpoint_conditions): Notify that breakpoint has
            changed after bumping hit count.
            (bpstat_stop_status): Likewise.
            (print_one_breakpoint_location): Don't wrap in tuple here.
            (print_one_breakpoint): Always print individual locations.
            For locations, use unnamed tuple.
            (disable_breakpoints_in_unloaded_shlib): Notify that breakpoint
            has changed.
            (create_catchpoint, create_syscall_event_catchpoint): Call
            breakpoint_created obsever.
            (mention): Don't call breakpoint_created observer.
            (create_breakpoint_sal): Call breakpoint_created observer.
            (create_breakpoint, watch_command_1): Likewise.
            (create_ada_exception_breakpoint): Likewise.
            (delete_breakpoint): Call breakpoint_deleted breakpoint.
            (locations_are_equal): New.
            (update_breakpoint_locations): If locations were changed, notify.
            (set_ignore_count, disable_breakpoint, do_enable_breakpoint):
            Call breakpoint_modified observer.
    
            * mi/mi-cmd-break.c (breakpoint_notify): Adjust.
            (mi_cmd_break_insert): Don't set observers for modify and delete.
            * mi/mi-interp.c (mi_suppress_breakpoint_notifications): New.
            (mi_breakpoint_created, mi_breakpoint_deleted)
            (mi_breakpoint_modified): New.
            (mi_interpreter_init): Hook the above.
            * mi/mi-main.c (mi_cmd_execute): Disable breakpoint notifications
            while -break-* commands are executing.
            * mi/mi-main.h (mi_suppress_breakpoint_notifications): New.
            * mi/mi-out.c (struct ui_out_data): New field original_buffer.
            (mi_redirect): New.
            (mi_ui_out_impl): Hook in mi_redirect.
            (mi_field_skip): True to the name, skip the field, don't output
            a field with an empty value.
    
            * python/py-breakpoint.c (gdbpy_breakpoint_created)
            (gdbpy_breakpoint_deleted): Adjust.
            * tui/tui-hooks.c (tui_event_create_breakpoint)
            (tui_event_delete_breakpoint, tui_event_modify_breakpoint): Adjust.
    
            * testsuite/gdb.mi/mi-cli.exp: Adust.
            * testsuite/gdb.mi/mi2-cli.exp: Adust.
            * testsuite/gdb.mi/mi-watch.exp: Adust.
            * testsuite/gdb.mi/mi2-watch.exp: Adust.
            * testsuite/lib/mi-support.exp (mi_expect_stop): Accept breakpoint
            notifications.

diff --git a/gdb/annotate.c b/gdb/annotate.c
index d24120c..2f0769a 100644
--- a/gdb/annotate.c
+++ b/gdb/annotate.c
@@ -32,7 +32,7 @@ extern void _initialize_annotate (void);
 
 static void print_value_flags (struct type *);
 
-static void breakpoint_changed (int);
+static void breakpoint_changed (struct breakpoint *b);
 
 
 void (*deprecated_annotate_signalled_hook) (void);
@@ -561,7 +561,7 @@ annotate_array_section_end (void)
 }
 
 static void
-breakpoint_changed (int bpno)
+breakpoint_changed (struct breakpoint *b)
 {
   breakpoints_changed ();
 }
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 3dbee85..bc08d7b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -626,7 +626,7 @@ set_breakpoint_condition (struct breakpoint *b, char *exp,
 	}
     }
   breakpoints_changed ();
-  observer_notify_breakpoint_modified (b->number);
+  observer_notify_breakpoint_modified (b);
 }
 
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
@@ -791,7 +791,7 @@ breakpoint_set_commands (struct breakpoint *b,
   decref_counted_command_line (&b->commands);
   b->commands = alloc_counted_command_line (commands);
   breakpoints_changed ();
-  observer_notify_breakpoint_modified (b->number);
+  observer_notify_breakpoint_modified (b);
 }
 
 /* Set the internal `silent' flag on the breakpoint.  Note that this
@@ -805,7 +805,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent)
 
   b->silent = silent;
   if (old_silent != silent)
-    observer_notify_breakpoint_modified (b->number);
+    observer_notify_breakpoint_modified (b);
 }
 
 /* Set the thread for this breakpoint.  If THREAD is -1, make the
@@ -818,7 +818,7 @@ breakpoint_set_thread (struct breakpoint *b, int thread)
 
   b->thread = thread;
   if (old_thread != thread)
-    observer_notify_breakpoint_modified (b->number);
+    observer_notify_breakpoint_modified (b);
 }
 
 /* Set the task for this breakpoint.  If TASK is 0, make the
@@ -831,7 +831,7 @@ breakpoint_set_task (struct breakpoint *b, int task)
 
   b->task = task;
   if (old_task != task)
-    observer_notify_breakpoint_modified (b->number);
+    observer_notify_breakpoint_modified (b);
 }
 
 void
@@ -908,7 +908,7 @@ do_map_commands_command (struct breakpoint *b, void *data)
       decref_counted_command_line (&b->commands);
       b->commands = info->cmd;
       breakpoints_changed ();
-      observer_notify_breakpoint_modified (b->number);
+      observer_notify_breakpoint_modified (b);
     }
 }
 
@@ -1672,6 +1672,7 @@ insert_bp_location (struct bp_location *bl,
 	      /* See also: disable_breakpoints_in_shlibs.  */
 	      val = 0;
 	      bl->shlib_disabled = 1;
+	      observer_notify_breakpoint_modified (bl->owner);
 	      if (!*disabled_breaks)
 		{
 		  fprintf_unfiltered (tmp_error_stream, 
@@ -4173,6 +4174,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
 	  bs->stop = 0;
 	  /* Increase the hit count even though we don't stop.  */
 	  ++(b->hit_count);
+	  observer_notify_breakpoint_modified (b);
 	}	
     }
 }
@@ -4301,6 +4303,7 @@ bpstat_stop_status (struct address_space *aspace,
 	  if (bs->stop)
 	    {
 	      ++(b->hit_count);
+	      observer_notify_breakpoint_modified (b);
 
 	      /* We will stop here.  */
 	      if (b->disposition == disp_disable)
@@ -4768,7 +4771,6 @@ print_one_breakpoint_location (struct breakpoint *b,
 {
   struct command_line *l;
   static char bpenables[] = "nynny";
-  struct cleanup *bkpt_chain;
 
   int header_of_multiple = 0;
   int part_of_multiple = (loc != NULL);
@@ -4787,7 +4789,6 @@ print_one_breakpoint_location (struct breakpoint *b,
     loc = b->loc;
 
   annotate_record ();
-  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
 
   /* 1 */
   annotate_field (0);
@@ -5052,8 +5053,6 @@ print_one_breakpoint_location (struct breakpoint *b,
       else if (b->exp_string)
 	ui_out_field_string (uiout, "original-location", b->exp_string);
     }
-	
-  do_cleanups (bkpt_chain);
 }
 
 static void
@@ -5061,7 +5060,12 @@ print_one_breakpoint (struct breakpoint *b,
 		      struct bp_location **last_loc, 
 		      int allflag)
 {
+  struct cleanup *bkpt_chain;
+
+  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
+
   print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
+  do_cleanups (bkpt_chain);
 
   /* If this breakpoint has custom print function,
      it's already printed.  Otherwise, print individual
@@ -5077,13 +5081,21 @@ print_one_breakpoint (struct breakpoint *b,
 	 internally, that's not a property exposed to user.  */
       if (b->loc 
 	  && !is_hardware_watchpoint (b)
-	  && (b->loc->next || !b->loc->enabled)
-	  && !ui_out_is_mi_like_p (uiout)) 
+	  && (b->loc->next || !b->loc->enabled))
 	{
+	  struct cleanup *inner = make_cleanup (null_cleanup, 0);
 	  struct bp_location *loc;
 	  int n = 1;
+
 	  for (loc = b->loc; loc; loc = loc->next, ++n)
-	    print_one_breakpoint_location (b, loc, n, last_loc, allflag);
+	    {
+	      struct cleanup *inner2 =
+		make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+	      print_one_breakpoint_location (b, loc, n, last_loc, allflag);
+	      do_cleanups (inner2);
+	    }
+
+	  do_cleanups (inner);
 	}
     }
 }
@@ -6191,6 +6203,10 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 	   succeeding so we must mark the breakpoint as not inserted
 	   to prevent future errors occurring in remove_breakpoints.  */
 	loc->inserted = 0;
+
+	/* This may cause duplicate notifications for the same breakpoint.  */
+	observer_notify_breakpoint_modified (b);
+
 	if (!disabled_shlib_breaks)
 	  {
 	    target_terminal_ours_for_output ();
@@ -6747,6 +6763,7 @@ create_catchpoint (struct gdbarch *gdbarch, int tempflag,
     create_catchpoint_without_mention (gdbarch, tempflag, cond_string, ops);
 
   mention (b);
+  observer_notify_breakpoint_created (b);
   update_global_location_list (1);
 
   return b;
@@ -6858,6 +6875,7 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter,
   /* Now, we have to mention the breakpoint and update the global
      location list.  */
   mention (b);
+  observer_notify_breakpoint_created (b);
   update_global_location_list (1);
 }
 
@@ -7094,12 +7112,6 @@ mention (struct breakpoint *b)
 
   get_user_print_options (&opts);
 
-  /* FIXME: This is misplaced; mention() is called by things (like
-     hitting a watchpoint) other than breakpoint creation.  It should
-     be possible to clean this up and at the same time replace the
-     random calls to breakpoint_changed with this hook.  */
-  observer_notify_breakpoint_created (b->number);
-
   if (b->ops != NULL && b->ops->print_mention != NULL)
     b->ops->print_mention (b);
   else
@@ -7454,12 +7466,11 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
       = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
 
   b->ops = ops;
-  if (internal)
-    /* Do not mention breakpoints with a negative number, but do
-       notify observers.  */
-    observer_notify_breakpoint_created (b->number);
-  else
+  /* Do not mention breakpoints with a negative number, but do
+     notify observers.  */
+  if (!internal)
     mention (b);
+  observer_notify_breakpoint_created (b);
 }
 
 /* Remove element at INDEX_TO_REMOVE from SAL, shifting other
@@ -8122,12 +8133,11 @@ create_breakpoint (struct gdbarch *gdbarch,
 	      || b->type == bp_hardware_breakpoint))
 	b->enable_state = bp_startup_disabled;
 
-      if (internal)
+      if (!internal)
         /* Do not mention breakpoints with a negative number, 
 	   but do notify observers.  */
-        observer_notify_breakpoint_created (b->number);
-      else
-        mention (b);
+	mention (b);
+      observer_notify_breakpoint_created (b);
     }
   
   if (sals.nelts > 1)
@@ -8631,6 +8641,7 @@ break_range_command (char *arg, int from_tty)
   discard_cleanups (cleanup_bkpt);
 
   mention (b);
+  observer_notify_breakpoint_created (b);
   update_global_location_list (1);
 }
 
@@ -9065,12 +9076,13 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
   /* Finally update the new watchpoint.  This creates the locations
      that should be inserted.  */
   update_watchpoint (b, 1);
-  if (internal)
-    /* Do not mention breakpoints with a negative number, but do
+
+  /* Do not mention breakpoints with a negative number, but do
        notify observers.  */
-    observer_notify_breakpoint_created (b->number);
-  else
+  if (!internal)
     mention (b);
+  observer_notify_breakpoint_created (b);
+
   update_global_location_list (1);
 }
 
@@ -9690,6 +9702,7 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch,
   b->ops = ops;
 
   mention (b);
+  observer_notify_breakpoint_created (b);
   update_global_location_list (1);
 }
 
@@ -10496,7 +10509,7 @@ delete_breakpoint (struct breakpoint *bpt)
       bpt->related_breakpoint = bpt;
     }
 
-  observer_notify_breakpoint_deleted (bpt->number);
+  observer_notify_breakpoint_deleted (bpt);
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;
@@ -10807,6 +10820,30 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
   return sal;
 }
 
+static int
+locations_are_equal (struct bp_location *a, struct bp_location *b)
+{
+  while (a && b)
+    {
+      if (a->address != b->address)
+	return 0;
+
+      if (a->shlib_disabled != b->shlib_disabled)
+	return 0;
+
+      if (a->enabled != b->enabled)
+	return 0;
+
+      a = a->next;
+      b = b->next;
+    }
+
+  if ((a == NULL) != (b == NULL))
+    return 0;
+
+  return 1;
+}
+
 /* Create new breakpoint locations for B (a hardware or software breakpoint)
    based on SALS and SALS_END.  If SALS_END.NELTS is not zero, then B is
    a ranged breakpoint.  */
@@ -10921,6 +10958,9 @@ update_breakpoint_locations (struct breakpoint *b,
       }
   }
 
+  if (!locations_are_equal (existing_locations, b->loc))
+    observer_notify_breakpoint_modified (b);
+
   update_global_location_list (1);
 }
 
@@ -11264,7 +11304,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
 			     count, bptnum);
 	}
       breakpoints_changed ();
-      observer_notify_breakpoint_modified (b->number);
+      observer_notify_breakpoint_modified (b);
       return;
     }
 
@@ -11419,7 +11459,7 @@ disable_breakpoint (struct breakpoint *bpt)
 
   update_global_location_list (0);
 
-  observer_notify_breakpoint_modified (bpt->number);
+  observer_notify_breakpoint_modified (bpt);
 }
 
 /* A callback for map_breakpoint_numbers that calls
@@ -11431,7 +11471,7 @@ do_map_disable_breakpoint (struct breakpoint *b, void *ignore)
   disable_breakpoint (b);
 }
 
-static void
+void
 disable_command (char *args, int from_tty)
 {
   struct breakpoint *bpt;
@@ -11510,7 +11550,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
   update_global_location_list (1);
   breakpoints_changed ();
   
-  observer_notify_breakpoint_modified (bpt->number);
+  observer_notify_breakpoint_modified (bpt);
 }
 
 
@@ -11533,7 +11573,7 @@ do_map_enable_breakpoint (struct breakpoint *b, void *ignore)
    breakpoints) so they once again become (or continue to be) effective
    in stopping the inferior.  */
 
-static void
+void
 enable_command (char *args, int from_tty)
 {
   struct breakpoint *bpt;
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e58dd57..15ccf2e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25191,6 +25191,19 @@ thread group in whose context the library was unloaded.  If the field is
 absent, it means the library was unloaded in the context of all present
 thread groups.
 
+@item =breakpoint-created,bkpt=@{...@}
+@itemx =breakpoint-modified,bkpt=@{...@}
+@itemx =breakpoint-deleted,bkpt=@{...@}
+Reports that a breakpoint was created, modified, or deleted,
+respectively.  Only user-visible breakpoints are reported to the MI
+user.
+
+The @var{bkpt} argument is of the same form as returned by the various
+breakpoint commands; @xref{GDB/MI Breakpoint Commands}.
+
+Note that if a breakpoint is emitted in the result record of a
+command, then it will not also be emitted in an async record.
+
 @end table
 
 @node GDB/MI Frame Information
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index d16c865..f103f3a 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -159,17 +159,16 @@ thread was resume, and may be RESUME_ALL if all threads are resumed.
 The target is about to be proceeded.
 @end deftypefun
 
-@deftypefun void breakpoint_created (int @var{bpnum})
-A new breakpoint has been created.  The argument @var{bpnum} is the
-number of the newly-created breakpoint.
+@deftypefun void breakpoint_created (struct breakpoint *@var{b})
+A new breakpoint @var{b} has been created.
 @end deftypefun
 
-@deftypefun void breakpoint_deleted (int @var{bpnum})
+@deftypefun void breakpoint_deleted (struct breakpoint *@var{b})
 A breakpoint has been destroyed.  The argument @var{bpnum} is the
 number of the newly-destroyed breakpoint.
 @end deftypefun
 
-@deftypefun void breakpoint_modified (int @var{bpnum})
+@deftypefun void breakpoint_modified (struct breakpoint *@var{b})
 A breakpoint has been modified in some way.  The argument @var{bpnum}
 is the number of the modified breakpoint.
 @end deftypefun
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index fe007a5..d68a033 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -29,6 +29,7 @@
 #include "gdb.h"
 #include "exceptions.h"
 #include "observer.h"
+#include "mi-main.h"
 
 enum
   {
@@ -46,10 +47,10 @@ static int mi_can_breakpoint_notify;
 /* Output a single breakpoint, when allowed. */
 
 static void
-breakpoint_notify (int b)
+breakpoint_notify (struct breakpoint *b)
 {
   if (mi_can_breakpoint_notify)
-    gdb_breakpoint_query (uiout, b, NULL);
+    gdb_breakpoint_query (uiout, b->number, NULL);
 }
 
 enum bp_type
@@ -146,8 +147,6 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
   if (! mi_breakpoint_observers_installed)
     {
       observer_attach_breakpoint_created (breakpoint_notify);
-      observer_attach_breakpoint_modified (breakpoint_notify);
-      observer_attach_breakpoint_deleted (breakpoint_notify);
       mi_breakpoint_observers_installed = 1;
     }
 
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 23c60f6..e9f5eca 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -35,6 +35,7 @@
 #include "observer.h"
 #include "gdbthread.h"
 #include "solist.h"
+#include "gdb.h"
 
 /* These are the interpreter setup, etc. functions for the MI interpreter */
 static void mi_execute_command_wrapper (char *cmd);
@@ -64,6 +65,9 @@ static void mi_on_resume (ptid_t ptid);
 static void mi_solib_loaded (struct so_list *solib);
 static void mi_solib_unloaded (struct so_list *solib);
 static void mi_about_to_proceed (void);
+static void mi_breakpoint_created (struct breakpoint *b);
+static void mi_breakpoint_deleted (struct breakpoint *b);
+static void mi_breakpoint_modified (struct breakpoint *b);
 
 static int report_initial_inferior (struct inferior *inf, void *closure);
 
@@ -99,6 +103,9 @@ mi_interpreter_init (int top_level)
       observer_attach_solib_loaded (mi_solib_loaded);
       observer_attach_solib_unloaded (mi_solib_unloaded);
       observer_attach_about_to_proceed (mi_about_to_proceed);
+      observer_attach_breakpoint_created (mi_breakpoint_created);
+      observer_attach_breakpoint_deleted (mi_breakpoint_deleted);
+      observer_attach_breakpoint_modified (mi_breakpoint_modified);
 
       /* The initial inferior is created before this function is called, so we
 	 need to report it explicitly.  Use iteration in case future version
@@ -445,6 +452,90 @@ mi_about_to_proceed (void)
   mi_proceeded = 1;
 }
 
+int mi_suppress_breakpoint_notifications = 0;
+
+static void
+mi_breakpoint_created (struct breakpoint *b)
+{
+  struct mi_interp *mi = top_level_interpreter_data ();
+  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+  struct gdb_exception e;
+
+  if (mi_suppress_breakpoint_notifications)
+    return;
+
+  if (b->number <= 0)
+    return;
+
+  target_terminal_ours ();
+  fprintf_unfiltered (mi->event_channel,
+		      "breakpoint-created");
+  /* We want the output from gdb_breakpoint_query to go to
+     mi->event_channel.  One approach would be to just
+     call gdb_breakpoint_query, and then use mi_out_put to
+     send the current content of mi_outout into mi->event_channel.
+     However, that will break if anything is output to mi_uiout
+     prior the calling the breakpoint_created notifications.
+     So, we use ui_out_redirect.  */
+  ui_out_redirect (mi_uiout, mi->event_channel);
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    gdb_breakpoint_query (mi_uiout, b->number, NULL);
+  ui_out_redirect (mi_uiout, NULL);
+
+  gdb_flush (mi->event_channel);
+}
+
+static void
+mi_breakpoint_deleted (struct breakpoint *b)
+{
+  struct mi_interp *mi = top_level_interpreter_data ();
+
+  if (mi_suppress_breakpoint_notifications)
+    return;
+
+  if (b->number <= 0)
+    return;
+
+  target_terminal_ours ();
+
+  fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
+		      b->number);
+
+  gdb_flush (mi->event_channel);
+}
+
+static void
+mi_breakpoint_modified (struct breakpoint *b)
+{
+  struct mi_interp *mi = top_level_interpreter_data ();
+  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+  struct gdb_exception e;
+
+  if (mi_suppress_breakpoint_notifications)
+    return;
+
+  if (b->number <= 0)
+    return;
+
+  target_terminal_ours ();
+  fprintf_unfiltered (mi->event_channel,
+		      "breakpoint-modified");
+  /* We want the output from gdb_breakpoint_query to go to
+     mi->event_channel.  One approach would be to just
+     call gdb_breakpoint_query, and then use mi_out_put to
+     send the current content of mi_outout into mi->event_channel.
+     However, that will break if anything is output to mi_uiout
+     prior the calling the breakpoint_created notifications.
+     So, we use ui_out_redirect.  */
+  ui_out_redirect (mi_uiout, mi->event_channel);
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    gdb_breakpoint_query (mi_uiout, b->number, NULL);
+  ui_out_redirect (mi_uiout, NULL);
+
+  gdb_flush (mi->event_channel);
+}
+
+
 static int
 mi_output_running_pid (struct thread_info *info, void *arg)
 {
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 6410e97..a78b6fd 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -2088,8 +2088,16 @@ mi_cmd_execute (struct mi_parse *parse)
 
   current_context = parse;
 
+  if (strstr (parse->command, "break-") == parse->command)
+    {
+      make_cleanup_restore_integer (&mi_suppress_breakpoint_notifications);
+      mi_suppress_breakpoint_notifications = 1;
+    }
+
   if (parse->cmd->argv_func != NULL)
-    parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+    {
+      parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
+    }
   else if (parse->cmd->cli.cmd != 0)
     {
       /* FIXME: DELETE THIS. */
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index 3ad6d0f..4de0983 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -33,6 +33,7 @@ extern char *current_token;
 
 extern int running_result_record_printed;
 extern int mi_proceeded;
+extern int mi_suppress_breakpoint_notifications;
 
 #endif
 
diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c
index 9aaeec6..ea77e50 100644
--- a/gdb/mi/mi-out.c
+++ b/gdb/mi/mi-out.c
@@ -30,6 +30,7 @@ struct ui_out_data
     int suppress_output;
     int mi_version;
     struct ui_file *buffer;
+    struct ui_file *original_buffer;
   };
 typedef struct ui_out_data mi_out_data;
 
@@ -63,6 +64,7 @@ static void mi_message (struct ui_out *uiout, int verbosity,
      ATTRIBUTE_PRINTF (3, 0);
 static void mi_wrap_hint (struct ui_out *uiout, char *identstring);
 static void mi_flush (struct ui_out *uiout);
+static int mi_redirect (struct ui_out *uiout, struct ui_file *outstream);
 
 /* This is the MI ui-out implementation functions vector */
 
@@ -86,7 +88,7 @@ struct ui_out_impl mi_ui_out_impl =
   mi_message,
   mi_wrap_hint,
   mi_flush,
-  NULL,
+  mi_redirect,
   1, /* Needs MI hacks.  */
 };
 
@@ -210,11 +212,6 @@ void
 mi_field_skip (struct ui_out *uiout, int fldno, int width,
                enum ui_align alignment, const char *fldname)
 {
-  mi_out_data *data = ui_out_data (uiout);
-
-  if (data->suppress_output)
-    return;
-  mi_field_string (uiout, fldno, width, alignment, fldname, "");
 }
 
 /* other specific mi_field_* end up here so alignment and field
@@ -294,6 +291,25 @@ mi_flush (struct ui_out *uiout)
   gdb_flush (data->buffer);
 }
 
+int
+mi_redirect (struct ui_out *uiout, struct ui_file *outstream)
+{
+  mi_out_data *data = ui_out_data (uiout);
+
+  if (outstream != NULL)
+    {
+      data->original_buffer = data->buffer;
+      data->buffer = outstream;
+    }
+  else if (data->original_buffer != NULL)
+    {
+      data->buffer = data->original_buffer;
+      data->original_buffer = NULL;
+    }
+
+  return 0;
+}
+
 /* local functions */
 
 /* access to ui_out format private members */
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 0c21bfc..ec43eb8 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -782,19 +782,11 @@ gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj)
 /* Callback that is used when a breakpoint is created.  This function
    will create a new Python breakpoint object.  */
 static void
-gdbpy_breakpoint_created (int num)
+gdbpy_breakpoint_created (struct breakpoint *bp)
 {
   breakpoint_object *newbp;
-  struct breakpoint *bp = NULL;
   PyGILState_STATE state;
 
-  bp = get_breakpoint (num);
-  if (! bp)
-    return;
-
-  if (num < 0 && bppy_pending_object == NULL)
-    return;
-
   if (bp->type != bp_breakpoint 
       && bp->type != bp_watchpoint
       && bp->type != bp_hardware_watchpoint  
@@ -813,7 +805,7 @@ gdbpy_breakpoint_created (int num)
     newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
   if (newbp)
     {
-      newbp->number = num;
+      newbp->number = bp->number;
       newbp->bp = bp;
       newbp->bp->py_bp_object = newbp;
       Py_INCREF (newbp);
@@ -832,8 +824,9 @@ gdbpy_breakpoint_created (int num)
 /* Callback that is used when a breakpoint is deleted.  This will
    invalidate the corresponding Python object.  */
 static void
-gdbpy_breakpoint_deleted (int num)
+gdbpy_breakpoint_deleted (struct breakpoint *b)
 {
+  int num = b->number;
   PyGILState_STATE state;
   struct breakpoint *bp = NULL;
   breakpoint_object *bp_obj;
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index e3096f8..d24f95f 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c
 #   {.*=breakpoint-delete,number=\"2\".*\^done} \
 #   "-interpreter-exec console \"delete 2\""
 mi_gdb_test "100-interpreter-exec console \"delete 2\"" \
-  {100\^done} \
+  {=breakpoint-deleted,id=\"2\"\r\n100\^done} \
   "-interpreter-exec console \"delete 2\""
 
 # NOTE: cagney/2003-02-03: Not yet.
diff --git a/gdb/testsuite/gdb.mi/mi-watch.exp b/gdb/testsuite/gdb.mi/mi-watch.exp
index 6b1db46..a2c69e1 100644
--- a/gdb/testsuite/gdb.mi/mi-watch.exp
+++ b/gdb/testsuite/gdb.mi/mi-watch.exp
@@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} {
              "break-watch operation"
 
     mi_gdb_test "222-break-list" \
-	    "222\\\^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=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",addr=\"\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \
+	    "222\\\^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=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \
                 "list of watchpoints"
 
 }
diff --git a/gdb/testsuite/gdb.mi/mi2-cli.exp b/gdb/testsuite/gdb.mi/mi2-cli.exp
index ba4a770..8dce12d 100644
--- a/gdb/testsuite/gdb.mi/mi2-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi2-cli.exp
@@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c
 #   {.*=breakpoint-delete,number=\"2\".*\^done} \
 #   "-interpreter-exec console \"delete 2\""
 mi_gdb_test "100-interpreter-exec console \"delete 2\"" \
-  {100\^done} \
+  {=breakpoint-deleted,id=\"2\"\r\n100\^done} \
   "-interpreter-exec console \"delete 2\""
 
 # NOTE: cagney/2003-02-03: Not yet.
diff --git a/gdb/testsuite/gdb.mi/mi2-watch.exp b/gdb/testsuite/gdb.mi/mi2-watch.exp
index 4c7d4a7..6ea2db0 100644
--- a/gdb/testsuite/gdb.mi/mi2-watch.exp
+++ b/gdb/testsuite/gdb.mi/mi2-watch.exp
@@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} {
              "break-watch operation"
 
     mi_gdb_test "222-break-list" \
-	    "222\\\^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=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",addr=\"\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \
+	    "222\\\^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=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \
                 "list of watchpoints"
 
 }
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index e75a4f5..e3f6b03 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -32,6 +32,7 @@ set MIFLAGS "-i=mi"
 
 set thread_selected_re "=thread-selected,id=\"\[0-9\]+\"\r\n"
 set library_loaded_re "=library-loaded\[^\n\]+\"\r\n"
+set breakpoint_re "=(breakpoint-created|breakpoint-deleted)\[^\n\]+\"\r\n"
 
 #
 # mi_gdb_exit -- exit the GDB, killing the target program if necessary
@@ -978,6 +979,7 @@ proc mi_expect_stop { reason func args file line extra test } {
     global fullname_syntax
     global async
     global thread_selected_re
+    global breakpoint_re
 
     set after_stopped ""
     set after_reason ""
@@ -1038,9 +1040,9 @@ proc mi_expect_stop { reason func args file line extra test } {
 
     set any "\[^\n\]*"
 
-    verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re"
+    verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
     gdb_expect {
-	-re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re" {
+	-re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" {
 	    pass "$test"
             return $expect_out(2,string)
 	}
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
index 97b99a7..bfe9b8b 100644
--- a/gdb/tui/tui-hooks.c
+++ b/gdb/tui/tui-hooks.c
@@ -137,7 +137,7 @@ tui_register_changed_hook (int regno)
 /* Breakpoint creation hook.
    Update the screen to show the new breakpoint.  */
 static void
-tui_event_create_breakpoint (int number)
+tui_event_create_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }
@@ -145,13 +145,13 @@ tui_event_create_breakpoint (int number)
 /* Breakpoint deletion hook.
    Refresh the screen to update the breakpoint marks.  */
 static void
-tui_event_delete_breakpoint (int number)
+tui_event_delete_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }
 
 static void
-tui_event_modify_breakpoint (int number)
+tui_event_modify_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]