2000-05-10 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index e1f97c7309bb9cd14431dfc39e84581be72ce14f..89b15909a71777579acefd89e09d28a5356f7c55 100644 (file)
@@ -39,6 +39,9 @@
 #include "annotate.h"
 #include "symfile.h"
 #include "objfiles.h"
+#ifdef UI_OUT
+#include "ui-out.h"
+#endif
 
 #include "gdb-events.h"
 
@@ -915,6 +918,7 @@ insert_breakpoints ()
              b->type == bp_read_watchpoint ||
              b->type == bp_access_watchpoint)
             && b->enable == enabled
+            && b->disposition != del_at_next_stop
             && !b->inserted
             && !b->duplicate)
       {
@@ -970,24 +974,39 @@ insert_breakpoints ()
                if (VALUE_LVAL (v) == lval_memory
                    && ! VALUE_LAZY (v))
                  {
-                   CORE_ADDR addr;
-                   int len, type;
-
-                   addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
-                   len = TYPE_LENGTH (VALUE_TYPE (v));
-                   type   = hw_write;
-                   if (b->type == bp_read_watchpoint)
-                     type = hw_read;
-                   else if (b->type == bp_access_watchpoint)
-                     type = hw_access;
-
-                   val = target_insert_watchpoint (addr, len, type);
-                   if (val == -1)
+                   struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+                   /* We only watch structs and arrays if user asked
+                      for it explicitly, never if they just happen to
+                      appear in the middle of some value chain.  */
+                   if (v == b->val_chain
+                       || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+                           && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
                      {
-                       b->inserted = 0;
-                       break;
+                       CORE_ADDR addr;
+                       int len, type;
+
+                       addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+                       len = TYPE_LENGTH (VALUE_TYPE (v));
+                       type   = hw_write;
+                       if (b->type == bp_read_watchpoint)
+                         type = hw_read;
+                       else if (b->type == bp_access_watchpoint)
+                         type = hw_access;
+
+                       val = target_insert_watchpoint (addr, len, type);
+                       if (val == -1)
+                         {
+                           /* Don't exit the loop, try to insert
+                              every value on the value chain.  That's
+                              because we will be removing all the
+                              watches below, and removing a
+                              watchpoint we didn't insert could have
+                              adverse effects.  */
+                           b->inserted = 0;
+                         }
+                       val = 0;
                      }
-                   val = 0;
                  }
              }
            /* Failure to insert a watchpoint on any memory value in the
@@ -1002,7 +1021,7 @@ insert_breakpoints ()
          }
        else
          {
-           printf_filtered ("Hardware watchpoint %d deleted", b->number);
+           printf_filtered ("Hardware watchpoint %d deleted ", b->number);
            printf_filtered ("because the program has left the block \n");
            printf_filtered ("in which its expression is valid.\n");
            if (b->related_breakpoint)
@@ -1013,7 +1032,7 @@ insert_breakpoints ()
        /* Restore the frame and level.  */
        if ((saved_frame != selected_frame) ||
            (saved_level != selected_frame_level))
-         select_and_print_frame (saved_frame, saved_level);
+         select_frame (saved_frame, saved_level);
 
        if (val)
          return_val = val;     /* remember failure */
@@ -1076,6 +1095,27 @@ remove_breakpoints ()
   return 0;
 }
 
+int
+remove_hw_watchpoints (void)
+{
+  register struct breakpoint *b;
+  int val;
+
+  ALL_BREAKPOINTS (b)
+  {
+    if (b->inserted
+       && (b->type == bp_hardware_watchpoint
+           || b->type == bp_read_watchpoint
+           || b->type == bp_access_watchpoint))
+      {
+       val = remove_breakpoint (b, mark_uninserted);
+       if (val != 0)
+         return val;
+      }
+  }
+  return 0;
+}
+
 int
 reattach_breakpoints (pid)
      int pid;
@@ -1323,21 +1363,28 @@ remove_breakpoint (b, is)
          if (VALUE_LVAL (v) == lval_memory
              && ! VALUE_LAZY (v))
            {
-             CORE_ADDR addr;
-             int len, type;
+             struct type *vtype = check_typedef (VALUE_TYPE (v));
 
-             addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
-             len = TYPE_LENGTH (VALUE_TYPE (v));
-             type   = hw_write;
-             if (b->type == bp_read_watchpoint)
-               type = hw_read;
-             else if (b->type == bp_access_watchpoint)
-               type = hw_access;
-
-             val = target_remove_watchpoint (addr, len, type);
-             if (val == -1)
-               b->inserted = 1;
-             val = 0;
+             if (v == b->val_chain
+                 || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+                     && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+               {
+                 CORE_ADDR addr;
+                 int len, type;
+
+                 addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+                 len = TYPE_LENGTH (VALUE_TYPE (v));
+                 type   = hw_write;
+                 if (b->type == bp_read_watchpoint)
+                   type = hw_read;
+                 else if (b->type == bp_access_watchpoint)
+                   type = hw_access;
+
+                 val = target_remove_watchpoint (addr, len, type);
+                 if (val == -1)
+                   b->inserted = 1;
+                 val = 0;
+               }
            }
        }
       /* Failure to remove any of the hardware watchpoints comes here.  */
@@ -1888,6 +1935,12 @@ static enum print_stop_action
 print_it_typical (bs)
      bpstat bs;
 {
+#ifdef UI_OUT
+  struct cleanup *old_chain;
+  struct ui_stream *stb;
+  stb = ui_out_stream_new (uiout);
+  old_chain = make_cleanup ((make_cleanup_func) ui_out_stream_delete, stb);
+#endif /* UI_OUT */
   /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
      which has since been deleted.  */
   if (bs->breakpoint_at == NULL)
@@ -1897,11 +1950,21 @@ print_it_typical (bs)
     {
     case bp_breakpoint:
     case bp_hardware_breakpoint:
+#ifdef UI_OUT
+      annotate_breakpoint (bs->breakpoint_at->number);
+      ui_out_text (uiout, "\nBreakpoint ");
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "breakpoint-hit");
+      ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number);
+      ui_out_text (uiout, ", ");
+      return PRINT_SRC_AND_LOC;
+#else
       /* I think the user probably only wants to see one breakpoint
          number, not all of them.  */
       annotate_breakpoint (bs->breakpoint_at->number);
       printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);
       return PRINT_SRC_AND_LOC;
+#endif
       break;
 
     case bp_shlib_event:
@@ -2034,6 +2097,20 @@ print_it_typical (bs)
       if (bs->old_val != NULL)
        {
          annotate_watchpoint (bs->breakpoint_at->number);
+#ifdef UI_OUT
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_field_string (uiout, "reason", "watchpoint-trigger");
+         mention (bs->breakpoint_at);
+         ui_out_list_begin (uiout, "value");
+         ui_out_text (uiout, "\nOld value = ");
+         value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+         ui_out_field_stream (uiout, "old", stb);
+         ui_out_text (uiout, "\nNew value = ");
+         value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+         ui_out_field_stream (uiout, "new", stb);
+         ui_out_list_end (uiout);
+         ui_out_text (uiout, "\n");
+#else
          mention (bs->breakpoint_at);
          printf_filtered ("\nOld value = ");
          value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
@@ -2041,6 +2118,7 @@ print_it_typical (bs)
          value_print (bs->breakpoint_at->val, gdb_stdout, 0,
                       Val_pretty_default);
          printf_filtered ("\n");
+#endif
          value_free (bs->old_val);
          bs->old_val = NULL;
        }
@@ -2049,15 +2127,55 @@ print_it_typical (bs)
       break;
 
     case bp_read_watchpoint:
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "read-watchpoint-trigger");
+      mention (bs->breakpoint_at);
+      ui_out_list_begin (uiout, "value");
+      ui_out_text (uiout, "\nValue = ");
+      value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+      ui_out_field_stream (uiout, "value", stb);
+      ui_out_list_end (uiout);
+      ui_out_text (uiout, "\n");
+#else
       mention (bs->breakpoint_at);
       printf_filtered ("\nValue = ");
       value_print (bs->breakpoint_at->val, gdb_stdout, 0,
                   Val_pretty_default);
       printf_filtered ("\n");
+#endif
       return PRINT_UNKNOWN;
       break;
 
     case bp_access_watchpoint:
+#ifdef UI_OUT
+      if (bs->old_val != NULL)     
+       {
+         annotate_watchpoint (bs->breakpoint_at->number);
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+         mention (bs->breakpoint_at);
+         ui_out_list_begin (uiout, "value");
+         ui_out_text (uiout, "\nOld value = ");
+         value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+         ui_out_field_stream (uiout, "old", stb);
+         value_free (bs->old_val);
+         bs->old_val = NULL;
+         ui_out_text (uiout, "\nNew value = ");
+       }
+      else 
+       {
+         mention (bs->breakpoint_at);
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_list_begin (uiout, "value");
+         ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+         ui_out_text (uiout, "\nValue = ");
+       }
+      value_print (bs->breakpoint_at->val, stb->stream, 0,Val_pretty_default);
+      ui_out_field_stream (uiout, "new", stb);
+      ui_out_list_end (uiout);
+      ui_out_text (uiout, "\n");
+#else
       if (bs->old_val != NULL)     
        {
          annotate_watchpoint (bs->breakpoint_at->number);
@@ -2076,6 +2194,7 @@ print_it_typical (bs)
       value_print (bs->breakpoint_at->val, gdb_stdout, 0,
                   Val_pretty_default);
       printf_filtered ("\n");
+#endif
       return PRINT_UNKNOWN;
       break;
 
@@ -2083,7 +2202,21 @@ print_it_typical (bs)
        here. */
 
     case bp_finish:
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "function-finished");
+#endif
+      return PRINT_UNKNOWN;
+      break;
+
     case bp_until:
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "location-reached");
+#endif
+      return PRINT_UNKNOWN;
+      break;
+
     case bp_none:
     case bp_longjmp:
     case bp_longjmp_resume:
@@ -2288,9 +2421,18 @@ watchpoint_check (p)
         in this case, by the time we call print_it_typical() this bp
         will be deleted already. So we have no choice but print the
         information here. */
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "watchpoint-scope");
+      ui_out_text (uiout, "\nWatchpoint ");
+      ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number);
+      ui_out_text (uiout, " deleted because the program has left the block in\n\
+which its expression is valid.\n");     
+#else
       printf_filtered ("\
 Watchpoint %d deleted because the program has left the block in\n\
 which its expression is valid.\n", bs->breakpoint_at->number);
+#endif 
 
       if (b->related_breakpoint)
        b->related_breakpoint->disposition = del_at_next_stop;
@@ -2472,14 +2614,21 @@ bpstat_stop_status (pc, not_a_breakpoint)
            if (VALUE_LVAL (v) == lval_memory
                && ! VALUE_LAZY (v))
              {
-               CORE_ADDR vaddr;
-
-               vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
-               /* Exact match not required.  Within range is sufficient.  
-                */
-               if (addr >= vaddr &&
-                   addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
-                 found = 1;
+               struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+               if (v == b->val_chain
+                   || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+                       && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+                 {
+                   CORE_ADDR vaddr;
+
+                   vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+                   /* Exact match not required.  Within range is
+                       sufficient.  */
+                   if (addr >= vaddr &&
+                       addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
+                     found = 1;
+                 }
              }
          }
        if (found)
@@ -2492,6 +2641,17 @@ bpstat_stop_status (pc, not_a_breakpoint)
              /* Stop.  */
              break;
            case WP_VALUE_CHANGED:
+             if (b->type == bp_read_watchpoint)
+               {
+                 /* Don't stop: read watchpoints shouldn't fire if
+                    the value has changed.  This is for targets which
+                    cannot set read-only watchpoints.  */
+                 bs->print_it = print_it_noop;
+                 bs->stop = 0;
+                 continue;
+               }
+             ++(b->hit_count);
+             break;
            case WP_VALUE_NOT_CHANGED:
              /* Stop.  */
              ++(b->hit_count);
@@ -3033,12 +3193,23 @@ print_one_breakpoint (struct breakpoint *b,
   {"del", "dstp", "dis", "keep"};
   static char bpenables[] = "nynny";
   char wrap_indent[80];
+#ifdef UI_OUT
+  struct ui_stream *stb = ui_out_stream_new (uiout);
+  struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
+#endif
 
   annotate_record ();
+#ifdef UI_OUT
+  ui_out_list_begin (uiout, "bkpt");
+#endif
 
   /* 1 */
   annotate_field (0);
+#ifdef UI_OUT
+  ui_out_field_int (uiout, "number", b->number);
+#else
   printf_filtered ("%-3d ", b->number);
+#endif
 
   /* 2 */
   annotate_field (1);
@@ -3046,15 +3217,28 @@ print_one_breakpoint (struct breakpoint *b,
       || ((int) b->type != bptypes[(int) b->type].type))
     internal_error ("bptypes table does not describe type #%d.",
                    (int) b->type);
+#ifdef UI_OUT
+  ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+#else
   printf_filtered ("%-14s ", bptypes[(int) b->type].description);
+#endif
 
   /* 3 */
   annotate_field (2);
+#ifdef UI_OUT
+  ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+#else
   printf_filtered ("%-4s ", bpdisps[(int) b->disposition]);
+#endif
 
   /* 4 */
   annotate_field (3);
+#ifdef UI_OUT
+  ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable]);
+  ui_out_spaces (uiout, 2);
+#else
   printf_filtered ("%-3c ", bpenables[(int) b->enable]);
+#endif
   
   /* 5 and 6 */
   strcpy (wrap_indent, "                           ");
@@ -3073,8 +3257,16 @@ print_one_breakpoint (struct breakpoint *b,
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      print_expression (b->exp, stb->stream);
+      ui_out_field_stream (uiout, "what", stb);
+#else
       annotate_field (5);
       print_expression (b->exp, gdb_stdout);
+#endif
       break;
       
     case bp_catch_load:
@@ -3082,11 +3274,28 @@ print_one_breakpoint (struct breakpoint *b,
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      if (b->dll_pathname == NULL)
+       {
+         ui_out_field_string (uiout, "what", "<any library>");
+         ui_out_spaces (uiout, 1);
+       }
+      else
+       {
+         ui_out_text (uiout, "library \"");
+         ui_out_field_string (uiout, "what", b->dll_pathname);
+         ui_out_text (uiout, "\" ");
+       }
+#else
       annotate_field (5);
       if (b->dll_pathname == NULL)
        printf_filtered ("<any library> ");
       else
        printf_filtered ("library \"%s\" ", b->dll_pathname);
+#endif
       break;
       
     case bp_catch_fork:
@@ -3094,34 +3303,74 @@ print_one_breakpoint (struct breakpoint *b,
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      if (b->forked_inferior_pid != 0)
+       {
+         ui_out_text (uiout, "process ");
+         ui_out_field_int (uiout, "what", b->forked_inferior_pid);
+         ui_out_spaces (uiout, 1);
+       }
+#else
       annotate_field (5);
       if (b->forked_inferior_pid != 0)
        printf_filtered ("process %d ", b->forked_inferior_pid);
       break;
+#endif
       
     case bp_catch_exec:
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      if (b->exec_pathname != NULL)
+       {
+         ui_out_text (uiout, "program \"");
+         ui_out_field_string (uiout, "what", b->exec_pathname);
+         ui_out_text (uiout, "\" ");
+       }
+#else
       annotate_field (5);
       if (b->exec_pathname != NULL)
        printf_filtered ("program \"%s\" ", b->exec_pathname);
+#endif
       break;
 
     case bp_catch_catch:
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      ui_out_field_string (uiout, "what", "exception catch");
+      ui_out_spaces (uiout, 1);
+#else
       annotate_field (5);
       printf_filtered ("exception catch ");
+#endif
       break;
 
     case bp_catch_throw:
       /* Field 4, the address, is omitted (which makes the columns
         not line up too nicely with the headers, but the effect
         is relatively readable).  */
+#ifdef UI_OUT
+      if (addressprint)
+       ui_out_field_skip (uiout, "addr");
+      annotate_field (5);
+      ui_out_field_string (uiout, "what", "exception throw");
+      ui_out_spaces (uiout, 1);
+#else
       annotate_field (5);
       printf_filtered ("exception throw ");
+#endif
       break;
       
     case bp_breakpoint:
@@ -3136,6 +3385,35 @@ print_one_breakpoint (struct breakpoint *b,
     case bp_call_dummy:
     case bp_shlib_event:
     case bp_thread_event:
+#ifdef UI_OUT
+      if (addressprint)
+       {
+         annotate_field (4);
+         ui_out_field_core_addr (uiout, "addr", b->address);
+       }
+      annotate_field (5);
+      *last_addr = b->address;
+      if (b->source_file)
+       {
+         sym = find_pc_sect_function (b->address, b->section);
+         if (sym)
+           {
+             ui_out_text (uiout, "in ");
+             ui_out_field_string (uiout, "func",
+                                  SYMBOL_SOURCE_NAME (sym));
+             ui_out_wrap_hint (uiout, wrap_indent);
+             ui_out_text (uiout, " at ");
+           }
+         ui_out_field_string (uiout, "file", b->source_file);
+         ui_out_text (uiout, ":");
+         ui_out_field_int (uiout, "line", b->line_number);
+       }
+      else
+       {
+         print_address_symbolic (b->address, stb->stream, demangle, "");
+         ui_out_field_stream (uiout, "at", stb);
+       }
+#else
       if (addressprint)
        {
          annotate_field (4);
@@ -3163,64 +3441,132 @@ print_one_breakpoint (struct breakpoint *b,
        }
       else
        print_address_symbolic (b->address, gdb_stdout, demangle, " ");
+#endif
       break;
     }
   
   if (b->thread != -1)
     {
+#ifdef UI_OUT
+      /* FIXME: This seems to be redundant and lost here; see the
+        "stop only in" line a little further down. */
+      ui_out_text (uiout, " thread ");
+      ui_out_field_int (uiout, "thread", b->thread);
+#else
       printf_filtered (" thread %d", b->thread);
+#endif
     }
   
+#ifdef UI_OUT
+  ui_out_text (uiout, "\n");
+#else
   printf_filtered ("\n");
+#endif
   
   if (b->frame)
     {
       annotate_field (6);
+#ifdef UI_OUT
+      ui_out_text (uiout, "\tstop only in stack frame at ");
+      ui_out_field_core_addr (uiout, "frame", b->frame);
+      ui_out_text (uiout, "\n");
+#else
       printf_filtered ("\tstop only in stack frame at ");
       print_address_numeric (b->frame, 1, gdb_stdout);
       printf_filtered ("\n");
+#endif
     }
   
   if (b->cond)
     {
       annotate_field (7);
+#ifdef UI_OUT
+      ui_out_text (uiout, "\tstop only if ");
+      print_expression (b->cond, stb->stream);
+      ui_out_field_stream (uiout, "cond", stb);
+      ui_out_text (uiout, "\n");
+#else
       printf_filtered ("\tstop only if ");
       print_expression (b->cond, gdb_stdout);
       printf_filtered ("\n");
+#endif
     }
   
   if (b->thread != -1)
     {
       /* FIXME should make an annotation for this */
+#ifdef UI_OUT
+      ui_out_text (uiout, "\tstop only in thread ");
+      ui_out_field_int (uiout, "thread", b->thread);
+      ui_out_text (uiout, "\n");
+#else
       printf_filtered ("\tstop only in thread %d\n", b->thread);
+#endif
     }
   
   if (show_breakpoint_hit_counts && b->hit_count)
     {
       /* FIXME should make an annotation for this */
+#ifdef UI_OUT
+      if (ep_is_catchpoint (b))
+       ui_out_text (uiout, "\tcatchpoint");
+      else
+       ui_out_text (uiout, "\tbreakpoint");
+      ui_out_text (uiout, " already hit ");
+      ui_out_field_int (uiout, "times", b->hit_count);
+      if (b->hit_count == 1)
+       ui_out_text (uiout, " time\n");
+      else
+       ui_out_text (uiout, " times\n");
+#else
       if (ep_is_catchpoint (b))
        printf_filtered ("\tcatchpoint");
       else
        printf_filtered ("\tbreakpoint");
       printf_filtered (" already hit %d time%s\n",
                       b->hit_count, (b->hit_count == 1 ? "" : "s"));
+#endif
     }
   
+#ifdef UI_OUT
+  /* Output the count also if it is zero, but only if this is
+     mi. FIXME: Should have a better test for this. */
+  if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+    if (show_breakpoint_hit_counts && b->hit_count == 0)
+      ui_out_field_int (uiout, "times", b->hit_count);
+#endif
+
   if (b->ignore_count)
     {
       annotate_field (8);
+#ifdef UI_OUT
+      ui_out_text (uiout, "\tignore next ");
+      ui_out_field_int (uiout, "ignore", b->ignore_count);
+      ui_out_text (uiout, " hits\n");
+#else
       printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+#endif
     }
   
   if ((l = b->commands))
     {
       annotate_field (9);
+#ifdef UI_OUT
+      ui_out_list_begin (uiout, "script");
+      print_command_lines (uiout, l, 4);
+      ui_out_list_end (uiout);
+#else
       while (l)
        {
          print_command_line (l, 4, gdb_stdout);
          l = l->next;
        }
+#endif
     }
+#ifdef UI_OUT
+  ui_out_list_end (uiout);
+  do_cleanups (old_chain);
+#endif
 }
 
 struct captured_breakpoint_query_args
@@ -3269,6 +3615,13 @@ breakpoint_1 (bnum, allflag)
   CORE_ADDR last_addr = (CORE_ADDR) -1;
   int found_a_breakpoint = 0;
   
+#ifdef UI_OUT
+  if (addressprint)
+    ui_out_table_begin (uiout, 6, "BreakpointTable");
+  else
+    ui_out_table_begin (uiout, 5, "BreakpointTable");
+#endif /* UI_OUT */
+
   ALL_BREAKPOINTS (b)
     if (bnum == -1
        || bnum == b->number)
@@ -3294,6 +3647,24 @@ breakpoint_1 (bnum, allflag)
        if (!found_a_breakpoint++)
          {
            annotate_breakpoints_headers ();
+#ifdef UI_OUT
+           annotate_field (0);
+           ui_out_table_header (uiout, 3, ui_left, "Num");     /* 1 */
+           annotate_field (1);
+           ui_out_table_header (uiout, 14, ui_left, "Type");   /* 2 */
+           annotate_field (2);
+           ui_out_table_header (uiout, 4, ui_left, "Disp");    /* 3 */
+           annotate_field (3);
+           ui_out_table_header (uiout, 3, ui_left, "Enb");     /* 4 */
+           if (addressprint)
+             {
+               annotate_field (4);
+               ui_out_table_header (uiout, 10, ui_left, "Address");    /* 5 */
+             }
+           annotate_field (5);
+           ui_out_table_header (uiout, 40, ui_noalign, "What");        /* 6 */
+           ui_out_table_body (uiout);
+#else
            annotate_field (0);
            printf_filtered ("Num ");
            annotate_field (1);
@@ -3309,6 +3680,7 @@ breakpoint_1 (bnum, allflag)
              }
            annotate_field (5);
            printf_filtered ("What\n");
+#endif /* UI_OUT */
            annotate_breakpoints_table ();
          }
        
@@ -3317,10 +3689,18 @@ breakpoint_1 (bnum, allflag)
   
   if (!found_a_breakpoint)
     {
+#ifdef UI_OUT
+      if (bnum == -1)
+       ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
+      else
+       ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n",
+                       bnum);
+#else
       if (bnum == -1)
        printf_filtered ("No breakpoints or watchpoints.\n");
       else
        printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum);
+#endif /* UI_OUT */
     }
   else
     {
@@ -3330,6 +3710,9 @@ breakpoint_1 (bnum, allflag)
        set_next_address (last_addr);
     }
 
+#ifdef UI_OUT
+  ui_out_table_end (uiout);
+#endif /* UI_OUT */
   /* FIXME? Should this be moved up so that it is only called when
      there have been breakpoints? */
   annotate_breakpoints_table_end ();
@@ -4070,6 +4453,13 @@ mention (b)
      struct breakpoint *b;
 {
   int say_where = 0;
+#ifdef UI_OUT
+  struct cleanup *old_chain;
+  struct ui_stream *stb;
+
+  stb = ui_out_stream_new (uiout);
+  old_chain = make_cleanup ((make_cleanup_func) ui_out_stream_delete, stb);
+#endif /* UI_OUT */
 
   /* FIXME: This is misplaced; mention() is called by things (like hitting a
      watchpoint) other than breakpoint creation.  It should be possible to
@@ -4085,6 +4475,26 @@ mention (b)
     case bp_none:
       printf_filtered ("(apparently deleted?) Eventpoint %d: ", b->number);
       break;
+#ifdef UI_OUT
+    case bp_watchpoint:
+      ui_out_text (uiout, "Watchpoint ");
+      ui_out_list_begin (uiout, "wpt");
+      ui_out_field_int (uiout, "number", b->number);
+      ui_out_text (uiout, ": ");
+      print_expression (b->exp, stb->stream);
+      ui_out_field_stream (uiout, "exp", stb);
+      ui_out_list_end (uiout);
+      break;
+    case bp_hardware_watchpoint:
+      ui_out_text (uiout, "Hardware watchpoint ");
+      ui_out_list_begin (uiout, "wpt");
+      ui_out_field_int (uiout, "number", b->number);
+      ui_out_text (uiout, ": ");
+      print_expression (b->exp, stb->stream);
+      ui_out_field_stream (uiout, "exp", stb);
+      ui_out_list_end (uiout);
+      break;
+#else
     case bp_watchpoint:
       printf_filtered ("Watchpoint %d: ", b->number);
       print_expression (b->exp, gdb_stdout);
@@ -4093,6 +4503,27 @@ mention (b)
       printf_filtered ("Hardware watchpoint %d: ", b->number);
       print_expression (b->exp, gdb_stdout);
       break;
+#endif
+#ifdef UI_OUT
+    case bp_read_watchpoint:
+      ui_out_text (uiout, "Hardware read watchpoint ");
+      ui_out_list_begin (uiout, "hw-rwpt");
+      ui_out_field_int (uiout, "number", b->number);
+      ui_out_text (uiout, ": ");
+      print_expression (b->exp, stb->stream);
+      ui_out_field_stream (uiout, "exp", stb);
+      ui_out_list_end (uiout);
+      break;
+    case bp_access_watchpoint:
+      ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
+      ui_out_list_begin (uiout, "hw-awpt");
+      ui_out_field_int (uiout, "number", b->number);
+      ui_out_text (uiout, ": ");
+      print_expression (b->exp, stb->stream);
+      ui_out_field_stream (uiout, "exp", stb);
+      ui_out_list_end (uiout);
+      break;
+#else
     case bp_read_watchpoint:
       printf_filtered ("Hardware read watchpoint %d: ", b->number);
       print_expression (b->exp, gdb_stdout);
@@ -4102,11 +4533,26 @@ mention (b)
                       b->number);
       print_expression (b->exp, gdb_stdout);
       break;
+#endif
     case bp_breakpoint:
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       {
+         say_where = 0;
+         break;
+       }
+#endif
       printf_filtered ("Breakpoint %d", b->number);
       say_where = 1;
       break;
     case bp_hardware_breakpoint:
+#ifdef UI_OUT
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       {
+         say_where = 0;
+         break;
+       }
+#endif
       printf_filtered ("Hardware assisted breakpoint %d", b->number);
       say_where = 1;
       break;
@@ -4160,111 +4606,146 @@ mention (b)
       TUIDO (((TuiOpaqueFuncPtr) tui_vAllSetHasBreakAt, b, 1));
       TUIDO (((TuiOpaqueFuncPtr) tuiUpdateAllExecInfos));
     }
+#ifdef UI_OUT
+  do_cleanups (old_chain);
+#endif
+#ifdef UI_OUT
+  if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+    return;
+#endif
   printf_filtered ("\n");
 }
 \f
 
-/* Set a breakpoint according to ARG (function, linenum or *address)
-   flag: first bit  : 0 non-temporary, 1 temporary.
-   second bit : 0 normal breakpoint, 1 hardware breakpoint. */
+/* Add SALS.nelts breakpoints to the breakpoint table.  For each
+   SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i],
+   COND[i] and COND_STRING[i] values.
+
+   NOTE: If the function succeeds, the caller is expected to cleanup
+   the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the
+   array contents).  If the function fails (error() is called), the
+   caller is expected to cleanups both the ADDR_STRING, COND_STRING,
+   COND and SALS arrays and each of those arrays contents. */
 
 static void
-break_command_1 (arg, flag, from_tty)
-     char *arg;
-     int flag, from_tty;
+create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
+                   struct expression **cond, char **cond_string,
+                   enum bptype type, enum bpdisp disposition,
+                   int thread, int ignore_count, int from_tty)
 {
-  int tempflag, hardwareflag;
-  struct symtabs_and_lines sals;
-  struct symtab_and_line sal;
-  register struct expression *cond = 0;
-  register struct breakpoint *b;
-
-  /* Pointers in arg to the start, and one past the end, of the condition.  */
-  char *cond_start = NULL;
-  char *cond_end = NULL;
-  /* Pointers in arg to the start, and one past the end,
-     of the address part.  */
-  char *addr_start = NULL;
-  char *addr_end = NULL;
-  struct cleanup *old_chain;
-  struct cleanup *canonical_strings_chain = NULL;
-  char **canonical = (char **) NULL;
-  int i;
-  int thread;
-
-  hardwareflag = flag & BP_HARDWAREFLAG;
-  tempflag = flag & BP_TEMPFLAG;
+  if (type == bp_hardware_breakpoint)
+    {
+      int i = hw_breakpoint_used_count ();
+      int target_resources_ok = 
+       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
+                                           i + sals.nelts, 0);
+      if (target_resources_ok == 0)
+       error ("No hardware breakpoint support in the target.");
+      else if (target_resources_ok < 0)
+       error ("Hardware breakpoints used exceeds limit.");
+    }
 
-  sals.sals = NULL;
-  sals.nelts = 0;
+  /* Now set all the breakpoints.  */
+  {
+    int i;
+    for (i = 0; i < sals.nelts; i++)
+      {
+       struct breakpoint *b;
+       struct symtab_and_line sal = sals.sals[i];
 
-  INIT_SAL (&sal);             /* initialize to zeroes */
+       if (from_tty)
+         describe_other_breakpoints (sal.pc, sal.section);
+       
+       b = set_raw_breakpoint (sal);
+       set_breakpoint_count (breakpoint_count + 1);
+       b->number = breakpoint_count;
+       b->type = type;
+       b->cond = cond[i];
+       b->thread = thread;
+       b->addr_string = addr_string[i];
+       b->cond_string = cond_string[i];
+       b->ignore_count = ignore_count;
+       b->enable = enabled;
+       b->disposition = disposition;
+       mention (b);
+      }
+  }    
+}
 
-  /* If no arg given, or if first arg is 'if ', use the default breakpoint. */
+/* Parse ARG which is assumed to be a SAL specification possibly
+   followed by conditionals.  On return, SALS contains an array of SAL
+   addresses found. ADDR_STRING contains a vector of (canonical)
+   address strings. ARG points to the end of the SAL. */
 
-  if (!arg || (arg[0] == 'i' && arg[1] == 'f'
-              && (arg[2] == ' ' || arg[2] == '\t')))
+void
+parse_breakpoint_sals (char **address,
+                      struct symtabs_and_lines *sals,
+                      char ***addr_string)
+{
+  char *addr_start = *address;
+  *addr_string = NULL;
+  /* If no arg given, or if first arg is 'if ', use the default
+     breakpoint. */
+  if ((*address) == NULL
+      || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
     {
       if (default_breakpoint_valid)
        {
-         sals.sals = (struct symtab_and_line *)
+         struct symtab_and_line sal;
+         INIT_SAL (&sal);              /* initialize to zeroes */
+         sals->sals = (struct symtab_and_line *)
            xmalloc (sizeof (struct symtab_and_line));
          sal.pc = default_breakpoint_address;
          sal.line = default_breakpoint_line;
          sal.symtab = default_breakpoint_symtab;
          sal.section = find_pc_overlay (sal.pc);
-         sals.sals[0] = sal;
-         sals.nelts = 1;
+         sals->sals[0] = sal;
+         sals->nelts = 1;
        }
       else
        error ("No default breakpoint address now.");
     }
   else
     {
-      addr_start = arg;
-
       /* Force almost all breakpoints to be in terms of the
          current_source_symtab (which is decode_line_1's default).  This
          should produce the results we want almost all of the time while
          leaving default_breakpoint_* alone.  */
       if (default_breakpoint_valid
          && (!current_source_symtab
-             || (arg && (*arg == '+' || *arg == '-'))))
-       sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
-                             default_breakpoint_line, &canonical);
+             || (strchr ("+-", (*address)[0]) != NULL)))
+       *sals = decode_line_1 (address, 1, default_breakpoint_symtab,
+                              default_breakpoint_line, addr_string);
       else
-       sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical);
-
-      addr_end = arg;
+       *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string);
     }
-
-  if (!sals.nelts)
-    return;
-
-  /* Make sure that all storage allocated in decode_line_1 gets freed
-     in case the following `for' loop errors out.  */
-  old_chain = make_cleanup (free, sals.sals);
-  if (canonical != (char **) NULL)
+  /* For any SAL that didn't have a canonical string, fill one in. */
+  if (sals->nelts > 0 && *addr_string == NULL)
+    *addr_string = xcalloc (sals->nelts, sizeof (char **));
+  if (addr_start != (*address))
     {
-      make_cleanup (free, canonical);
-      canonical_strings_chain = make_cleanup (null_cleanup, 0);
-      for (i = 0; i < sals.nelts; i++)
+      int i;
+      for (i = 0; i < sals->nelts; i++)
        {
-         if (canonical[i] != NULL)
-           make_cleanup (free, canonical[i]);
+         /* Add the string if not present. */
+         if ((*addr_string)[i] == NULL)
+           (*addr_string)[i] = savestring (addr_start, (*address) - addr_start);
        }
     }
+}
 
-  thread = -1;                 /* No specific thread yet */
 
-  /* Resolve all line numbers to PC's, and verify that conditions
-     can be parsed, before setting any breakpoints.  */
-  for (i = 0; i < sals.nelts; i++)
-    {
-      char *tok, *end_tok;
-      int toklen;
+/* Convert each SAL into a real PC.  Verify that the PC can be
+   inserted as a breakpoint.  If it can't throw an error. */
 
-      resolve_sal_pc (&sals.sals[i]);
+void
+breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
+                      char *address)
+{    
+  int i;
+  for (i = 0; i < sals->nelts; i++)
+    {
+      resolve_sal_pc (&sals->sals[i]);
 
       /* It's possible for the PC to be nonzero, but still an illegal
          value on some targets.
@@ -4279,16 +4760,100 @@ break_command_1 (arg, flag, from_tty)
 
          Give the target a chance to bless sals.sals[i].pc before we
          try to make a breakpoint for it. */
-      if (PC_REQUIRES_RUN_BEFORE_USE (sals.sals[i].pc))
+      if (PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
        {
-         error ("Cannot break on %s without a running program.", 
-                addr_start);
+         if (address == NULL)
+           error ("Cannot break without a running program.");
+         else
+           error ("Cannot break on %s without a running program.", 
+                  address);
        }
+    }
+}
 
-      tok = arg;
+/* Set a breakpoint according to ARG (function, linenum or *address)
+   flag: first bit  : 0 non-temporary, 1 temporary.
+   second bit : 0 normal breakpoint, 1 hardware breakpoint. */
 
+static void
+break_command_1 (arg, flag, from_tty)
+     char *arg;
+     int flag, from_tty;
+{
+  int tempflag, hardwareflag;
+  struct symtabs_and_lines sals;
+  register struct expression **cond = 0;
+  /* Pointers in arg to the start, and one past the end, of the
+     condition.  */
+  char **cond_string = (char **) NULL;
+  char *addr_start = arg;
+  char **addr_string;
+  struct cleanup *old_chain;
+  struct cleanup *breakpoint_chain = NULL;
+  int i;
+  int thread = -1;
+  int ignore_count = 0;
+
+  hardwareflag = flag & BP_HARDWAREFLAG;
+  tempflag = flag & BP_TEMPFLAG;
+
+  sals.sals = NULL;
+  sals.nelts = 0;
+  addr_string = NULL;
+  parse_breakpoint_sals (&arg, &sals, &addr_string);
+
+  if (!sals.nelts)
+    return;
+
+  /* Create a chain of things that always need to be cleaned up. */
+  old_chain = make_cleanup (null_cleanup, 0);
+
+  /* Make sure that all storage allocated to SALS gets freed.  */
+  make_cleanup (free, sals.sals);
+
+  /* Cleanup the addr_string array but not its contents. */
+  make_cleanup (free, addr_string);
+
+  /* Allocate space for all the cond expressions. */
+  cond = xcalloc (sals.nelts, sizeof (struct expression *));
+  make_cleanup (free, cond);
+
+  /* Allocate space for all the cond strings. */
+  cond_string = xcalloc (sals.nelts, sizeof (char **));
+  make_cleanup (free, cond_string);
+
+  /* ----------------------------- SNIP -----------------------------
+     Anything added to the cleanup chain beyond this point is assumed
+     to be part of a breakpoint.  If the breakpoint create succeeds
+     then the memory is not reclaimed. */
+  breakpoint_chain = make_cleanup (null_cleanup, 0);
+
+  /* Mark the contents of the addr_string for cleanup.  These go on
+     the breakpoint_chain and only occure if the breakpoint create
+     fails. */
+  for (i = 0; i < sals.nelts; i++)
+    {
+      if (addr_string[i] != NULL)
+       make_cleanup (free, addr_string[i]);
+    }
+
+  /* Resolve all line numbers to PC's and verify that the addresses
+     are ok for the target.  */
+  breakpoint_sals_to_pc (&sals, addr_start);
+
+  /* Verify that condition can be parsed, before setting any
+     breakpoints.  Allocate a separate condition expression for each
+     breakpoint. */
+  thread = -1;                 /* No specific thread yet */
+  for (i = 0; i < sals.nelts; i++)
+    {
+      char *tok = arg;
       while (tok && *tok)
        {
+         char *end_tok;
+         int toklen;
+         char *cond_start = NULL;
+         char *cond_end = NULL;
          while (*tok == ' ' || *tok == '\t')
            tok++;
 
@@ -4302,8 +4867,11 @@ break_command_1 (arg, flag, from_tty)
          if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
            {
              tok = cond_start = end_tok + 1;
-             cond = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+             cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+             make_cleanup (free, cond[i]);
              cond_end = tok;
+             cond_string[i] = savestring (cond_start, cond_end - cond_start);
+             make_cleanup (free, cond_string[i]);
            }
          else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
            {
@@ -4321,61 +4889,149 @@ break_command_1 (arg, flag, from_tty)
            error ("Junk at end of arguments.");
        }
     }
-  if (hardwareflag)
-    {
-      int i, target_resources_ok;
 
-      i = hw_breakpoint_used_count ();
-      target_resources_ok = 
-       TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, 
-                                           i + sals.nelts, 0);
-      if (target_resources_ok == 0)
-       error ("No hardware breakpoint support in the target.");
-      else if (target_resources_ok < 0)
-       error ("Hardware breakpoints used exceeds limit.");
+  create_breakpoints (sals, addr_string, cond, cond_string,
+                     hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
+                     tempflag ? del : donttouch,
+                     thread, ignore_count, from_tty);
+
+  if (sals.nelts > 1)
+    {
+      warning ("Multiple breakpoints were set.");
+      warning ("Use the \"delete\" command to delete unwanted breakpoints.");
     }
+  /* That's it. Discard the cleanups for data inserted into the
+     breakpoint. */
+  discard_cleanups (breakpoint_chain);
+  /* But cleanup everything else. */
+  do_cleanups (old_chain);
+}
 
-  /* Remove the canonical strings from the cleanup, they are needed below.  */
-  if (canonical != (char **) NULL)
-    discard_cleanups (canonical_strings_chain);
+/* Set a breakpoint of TYPE/DISPOSITION according to ARG (function,
+   linenum or *address) with COND and IGNORE_COUNT. */
 
-  /* Now set all the breakpoints.  */
-  for (i = 0; i < sals.nelts; i++)
-    {
-      sal = sals.sals[i];
+struct captured_breakpoint_args
+  {
+    char *address;
+    char *condition;
+    int hardwareflag;
+    int tempflag;
+    int thread;
+    int ignore_count;
+  };
 
-      if (from_tty)
-       describe_other_breakpoints (sal.pc, sal.section);
+static int
+do_captured_breakpoint (void *data)
+{
+  struct captured_breakpoint_args *args = data;
+  struct symtabs_and_lines sals;
+  register struct expression **cond;
+  struct cleanup *old_chain;
+  struct cleanup *breakpoint_chain = NULL;
+  int i;
+  char **addr_string;
+  char **cond_string;
 
-      b = set_raw_breakpoint (sal);
-      set_breakpoint_count (breakpoint_count + 1);
-      b->number = breakpoint_count;
-      b->type = hardwareflag ? bp_hardware_breakpoint : bp_breakpoint;
-      b->cond = cond;
-      b->thread = thread;
+  char *address_end;
 
-      /* If a canonical line spec is needed use that instead of the
-         command string.  */
-      if (canonical != (char **) NULL && canonical[i] != NULL)
-       b->addr_string = canonical[i];
-      else if (addr_start)
-       b->addr_string = savestring (addr_start, addr_end - addr_start);
-      if (cond_start)
-       b->cond_string = savestring (cond_start, cond_end - cond_start);
+  /* Parse the source and lines spec.  Delay check that the expression
+     didn't contain trailing garbage until after cleanups are in
+     place. */
+  sals.sals = NULL;
+  sals.nelts = 0;
+  address_end = args->address;
+  addr_string = NULL;
+  parse_breakpoint_sals (&address_end, &sals, &addr_string);
 
-      b->enable = enabled;
-      b->disposition = tempflag ? del : donttouch;
-      mention (b);
+  if (!sals.nelts)
+    return GDB_RC_NONE;
+
+  /* Create a chain of things at always need to be cleaned up. */
+  old_chain = make_cleanup (null_cleanup, 0);
+
+  /* Always have a addr_string array, even if it is empty. */
+  make_cleanup (free, addr_string);
+
+  /* Make sure that all storage allocated to SALS gets freed.  */
+  make_cleanup (free, sals.sals);
+
+  /* Allocate space for all the cond expressions. */
+  cond = xcalloc (sals.nelts, sizeof (struct expression *));
+  make_cleanup (free, cond);
+
+  /* Allocate space for all the cond strings. */
+  cond_string = xcalloc (sals.nelts, sizeof (char **));
+  make_cleanup (free, cond_string);
+
+  /* ----------------------------- SNIP -----------------------------
+     Anything added to the cleanup chain beyond this point is assumed
+     to be part of a breakpoint.  If the breakpoint create goes
+     through then that memory is not cleaned up. */
+  breakpoint_chain = make_cleanup (null_cleanup, 0);
+
+  /* Mark the contents of the addr_string for cleanup.  These go on
+     the breakpoint_chain and only occure if the breakpoint create
+     fails. */
+  for (i = 0; i < sals.nelts; i++)
+    {
+      if (addr_string[i] != NULL)
+       make_cleanup (free, addr_string[i]);
     }
 
-  if (sals.nelts > 1)
+  /* Wait until now before checking for garbage at the end of the
+     address. That way cleanups can take care of freeing any
+     memory. */
+  if (*address_end != '\0')
+    error ("Garbage %s following breakpoint address", address_end);
+
+  /* Resolve all line numbers to PC's.  */
+  breakpoint_sals_to_pc (&sals, args->address);
+
+  /* Verify that conditions can be parsed, before setting any
+     breakpoints.  */
+  for (i = 0; i < sals.nelts; i++)
     {
-      warning ("Multiple breakpoints were set.");
-      warning ("Use the \"delete\" command to delete unwanted breakpoints.");
+      if (args->condition != NULL)
+       {
+         char *tok = args->condition;
+         cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+         if (*tok != '\0')
+           error ("Garbage %s follows condition", tok);
+         make_cleanup (free, cond[i]);
+         cond_string[i] = xstrdup (args->condition);
+       }
     }
+
+  create_breakpoints (sals, addr_string, cond, cond_string,
+                     args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
+                     args->tempflag ? del : donttouch,
+                     args->thread, args->ignore_count, 0/*from-tty*/);
+
+  /* That's it. Discard the cleanups for data inserted into the
+     breakpoint. */
+  discard_cleanups (breakpoint_chain);
+  /* But cleanup everything else. */
   do_cleanups (old_chain);
+  return GDB_RC_OK;
+}
+
+enum gdb_rc
+gdb_breakpoint (char *address, char *condition,
+               int hardwareflag, int tempflag,
+               int thread, int ignore_count)
+{
+  struct captured_breakpoint_args args;
+  args.address = address;
+  args.condition = condition;
+  args.hardwareflag = hardwareflag;
+  args.tempflag = tempflag;
+  args.thread = thread;
+  args.ignore_count = ignore_count;
+  return catch_errors (do_captured_breakpoint, &args,
+                      NULL, RETURN_MASK_ALL);
 }
 
+
 static void
 break_at_finish_at_depth_command_1 (arg, flag, from_tty)
      char *arg;
@@ -4920,6 +5576,7 @@ can_use_hardware_watchpoint (v)
      struct value *v;
 {
   int found_memory_cnt = 0;
+  struct value *head = v;
 
   /* Did the user specifically forbid us to use hardware watchpoints? */
   if (!can_use_hw_watchpoints)
@@ -4957,13 +5614,23 @@ can_use_hardware_watchpoint (v)
            {
              /* Ahh, memory we actually used!  Check if we can cover
                  it with hardware watchpoints.  */
-             CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
-             int       len   = TYPE_LENGTH (VALUE_TYPE (v));
+             struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+             /* We only watch structs and arrays if user asked for it
+                explicitly, never if they just happen to appear in a
+                middle of some value chain.  */
+             if (v == head
+                 || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+                     && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+               {
+                 CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+                 int       len   = TYPE_LENGTH (VALUE_TYPE (v));
 
-             if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
-               return 0;
-             else
-               found_memory_cnt++;
+                 if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+                   return 0;
+                 else
+                   found_memory_cnt++;
+               }
            }
        }
       else if (v->lval != not_lval && v->modifiable == 0)
@@ -4977,6 +5644,15 @@ can_use_hardware_watchpoint (v)
   return found_memory_cnt;
 }
 
+#ifdef UI_OUT
+void
+watch_command_wrapper (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  watch_command (arg, from_tty);
+}
+#endif
 static void
 watch_command (arg, from_tty)
      char *arg;
@@ -4985,6 +5661,15 @@ watch_command (arg, from_tty)
   watch_command_1 (arg, hw_write, from_tty);
 }
 
+#ifdef UI_OUT
+void
+rwatch_command_wrapper (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  rwatch_command (arg, from_tty);
+}
+#endif
 static void
 rwatch_command (arg, from_tty)
      char *arg;
@@ -4993,6 +5678,15 @@ rwatch_command (arg, from_tty)
   watch_command_1 (arg, hw_read, from_tty);
 }
 
+#ifdef UI_OUT
+void
+awatch_command_wrapper (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  awatch_command (arg, from_tty);
+}
+#endif
 static void
 awatch_command (arg, from_tty)
      char *arg;
@@ -5012,10 +5706,10 @@ awatch_command (arg, from_tty)
 static void
 until_break_command_continuation (struct continuation_arg *arg)
 {
-  /* Do all the exec cleanups, which at this point should only be the
-     one set up in the first part of the until_break_command
-     function. */
-  do_exec_cleanups (ALL_CLEANUPS);
+  struct cleanup *cleanups;
+
+  cleanups = (struct cleanup *) arg->data.pointer;
+  do_exec_cleanups (cleanups);
 }
 
 /* ARGSUSED */
@@ -5029,6 +5723,8 @@ until_break_command (arg, from_tty)
   struct frame_info *prev_frame = get_prev_frame (selected_frame);
   struct breakpoint *breakpoint;
   struct cleanup *old_chain;
+  struct continuation_arg *arg1;
+
 
   clear_proceed_status ();
 
@@ -5059,7 +5755,7 @@ until_break_command (arg, from_tty)
     old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, 
                              breakpoint);
   else
-    make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+    old_chain = make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
 
   /* If we are running asynchronously, and the target supports async
      execution, we are not waiting for the target to stop, in the call
@@ -5070,11 +5766,16 @@ until_break_command (arg, from_tty)
 
   if (event_loop_p && target_can_async_p ())
     {
-      /* In this case we don't need args for the continuation, because
-         all it needs to do is do the cleanups in the
-         exec_cleanup_chain, which will be only those inserted by this
-         function. We can get away by using ALL_CLEANUPS. */
-      add_continuation (until_break_command_continuation, NULL);
+      /* In this case the arg for the continuation is just the point
+         in the exec_cleanups chain from where to start doing
+         cleanups, because all the continuation does is the cleanups in
+         the exec_cleanup_chain. */
+      arg1 =
+       (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg1->next         = NULL;
+      arg1->data.pointer = old_chain;
+
+      add_continuation (until_break_command_continuation, arg1);
     }
 
   /* Keep within the current frame */
@@ -6908,8 +7609,7 @@ have been allocated for other watchpoints.\n", bpt->number);
        }
 
       if (save_selected_frame_level >= 0)
-       select_and_print_frame (save_selected_frame,
-                               save_selected_frame_level);
+       select_frame (save_selected_frame, save_selected_frame_level);
       value_free_to_mark (mark);
     }
   if (modify_breakpoint_hook)
This page took 0.041505 seconds and 4 git commands to generate.