* read.c (cons_worker): Detect and reject unexpected string argument.
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index a6bde43f37f6e7bb09fdce80e834a7998f4bd337..3dca17ec9b74009907ed644313ce5193dcbf280b 100644 (file)
@@ -130,7 +130,9 @@ static int watchpoint_locations_match (struct bp_location *loc1,
 
 static void breakpoints_info (char *, int);
 
-static void breakpoint_1 (int, int);
+static void watchpoints_info (char *, int);
+
+static int breakpoint_1 (int, int, int (*) (const struct breakpoint *));
 
 static bpstat bpstat_alloc (const struct bp_location *, bpstat);
 
@@ -204,9 +206,9 @@ static void update_global_location_list (int);
 
 static void update_global_location_list_nothrow (int);
 
-static int is_hardware_watchpoint (struct breakpoint *bpt);
+static int is_hardware_watchpoint (const struct breakpoint *bpt);
 
-static int is_watchpoint (struct breakpoint *bpt);
+static int is_watchpoint (const struct breakpoint *bpt);
 
 static void insert_breakpoint_locations (void);
 
@@ -222,6 +224,22 @@ static void disable_trace_command (char *, int);
 
 static void trace_pass_command (char *, int);
 
+/* A reference-counted struct command_line.  This lets multiple
+   breakpoints share a single command list.  */
+struct counted_command_line
+{
+  /* The reference count.  */
+  int refc;
+
+  /* The command list.  */
+  struct command_line *commands;
+};
+
+struct command_line *
+breakpoint_commands (struct breakpoint *b)
+{
+  return b->commands ? b->commands->commands : NULL;
+}
 
 /* Flag indicating that a command has proceeded the inferior past the
    current breakpoint.  */
@@ -350,7 +368,7 @@ static int overlay_events_enabled;
 
 #define ALL_TRACEPOINTS(B)  \
   for (B = breakpoint_chain; B; B = B->next)  \
-    if (tracepoint_type (B))
+    if (is_tracepoint (B))
 
 /* Chains of all breakpoints defined.  */
 
@@ -388,18 +406,20 @@ VEC(bp_location_p) *moribund_locations = NULL;
 
 static int breakpoint_count;
 
-/* If the last command to create a breakpoint created multiple
-   breakpoints, this holds the start and end breakpoint numbers.  */
-static int multi_start;
-static int multi_end;
-/* True if the last breakpoint set was part of a group set with a
-   single command, e.g., "rbreak".  */
-static int last_was_multi;
+/* The value of `breakpoint_count' before the last command that
+   created breakpoints.  If the last (break-like) command created more
+   than one breakpoint, then the difference between BREAKPOINT_COUNT
+   and PREV_BREAKPOINT_COUNT is more than one.  */
+static int prev_breakpoint_count;
 
 /* Number of last tracepoint made.  */
 
 static int tracepoint_count;
 
+static struct cmd_list_element *breakpoint_set_cmdlist;
+static struct cmd_list_element *breakpoint_show_cmdlist;
+static struct cmd_list_element *save_cmdlist;
+
 /* Return whether a breakpoint is an active enabled breakpoint.  */
 static int
 breakpoint_enabled (struct breakpoint *b)
@@ -412,29 +432,31 @@ breakpoint_enabled (struct breakpoint *b)
 static void
 set_breakpoint_count (int num)
 {
+  prev_breakpoint_count = breakpoint_count;
   breakpoint_count = num;
-  last_was_multi = 0;
   set_internalvar_integer (lookup_internalvar ("bpnum"), num);
 }
 
+/* Used by `start_rbreak_breakpoints' below, to record the current
+   breakpoint count before "rbreak" creates any breakpoint.  */
+static int rbreak_start_breakpoint_count;
+
 /* Called at the start an "rbreak" command to record the first
    breakpoint made.  */
+
 void
 start_rbreak_breakpoints (void)
 {
-  multi_start = breakpoint_count + 1;
+  rbreak_start_breakpoint_count = breakpoint_count;
 }
 
 /* Called at the end of an "rbreak" command to record the last
    breakpoint made.  */
+
 void
 end_rbreak_breakpoints (void)
 {
-  if (breakpoint_count >= multi_start)
-    {
-      multi_end = breakpoint_count;
-      last_was_multi = 1;
-    }
+  prev_breakpoint_count = rbreak_start_breakpoint_count;
 }
 
 /* Used in run_command to zero the hit count when a new run starts. */
@@ -448,14 +470,6 @@ clear_breakpoint_hit_counts (void)
     b->hit_count = 0;
 }
 
-/* Encapsulate tests for different types of tracepoints.  */
-
-static int
-tracepoint_type (const struct breakpoint *b)
-{
-  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
-}
-  
 /* Allocate a new counted_command_line with reference count of 1.
    The new structure owns COMMANDS.  */
 
@@ -699,6 +713,61 @@ get_breakpoint (int num)
 }
 
 \f
+
+void
+set_breakpoint_condition (struct breakpoint *b, char *exp,
+                         int from_tty)
+{
+  struct bp_location *loc = b->loc;
+
+  for (; loc; loc = loc->next)
+    {
+      xfree (loc->cond);
+      loc->cond = NULL;
+    }
+  xfree (b->cond_string);
+  b->cond_string = NULL;
+  xfree (b->cond_exp);
+  b->cond_exp = NULL;
+
+  if (*exp == 0)
+    {
+      if (from_tty)
+       printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
+    }
+  else
+    {
+      char *arg = exp;
+      /* I don't know if it matters whether this is the string the user
+        typed in or the decompiled expression.  */
+      b->cond_string = xstrdup (arg);
+      b->condition_not_parsed = 0;
+
+      if (is_watchpoint (b))
+       {
+         innermost_block = NULL;
+         arg = exp;
+         b->cond_exp = parse_exp_1 (&arg, 0, 0);
+         if (*arg)
+           error (_("Junk at end of expression"));
+         b->cond_exp_valid_block = innermost_block;
+       }
+      else
+       {
+         for (loc = b->loc; loc; loc = loc->next)
+           {
+             arg = exp;
+             loc->cond =
+               parse_exp_1 (&arg, block_for_pc (loc->address), 0);
+             if (*arg)
+               error (_("Junk at end of expression"));
+           }
+       }
+    }
+  breakpoints_changed ();
+  observer_notify_breakpoint_modified (b->number);
+}
+
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
 
 static void
@@ -719,53 +788,7 @@ condition_command (char *arg, int from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
       {
-       struct bp_location *loc = b->loc;
-       for (; loc; loc = loc->next)
-         {
-           xfree (loc->cond);
-           loc->cond = NULL;
-         }
-       xfree (b->cond_string);
-       b->cond_string = NULL;
-       xfree (b->cond_exp);
-       b->cond_exp = NULL;
-
-       if (*p == 0)
-         {
-           if (from_tty)
-             printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
-         }
-       else
-         {
-           arg = p;
-           /* I don't know if it matters whether this is the string the user
-              typed in or the decompiled expression.  */
-           b->cond_string = xstrdup (arg);
-           b->condition_not_parsed = 0;
-
-           if (is_watchpoint (b))
-             {
-               innermost_block = NULL;
-               arg = p;
-               b->cond_exp = parse_exp_1 (&arg, 0, 0);
-               if (*arg)
-                 error (_("Junk at end of expression"));
-               b->cond_exp_valid_block = innermost_block;
-             }
-           else
-             {
-               for (loc = b->loc; loc; loc = loc->next)
-                 {
-                   arg = p;
-                   loc->cond =
-                     parse_exp_1 (&arg, block_for_pc (loc->address), 0);
-                   if (*arg)
-                     error (_("Junk at end of expression"));
-                 }
-             }
-         }
-       breakpoints_changed ();
-       observer_notify_breakpoint_modified (b->number);
+       set_breakpoint_condition (b, p, from_tty);
        return;
       }
 
@@ -801,20 +824,14 @@ check_no_tracepoint_commands (struct command_line *commands)
     }
 }
 
+/* Encapsulate tests for different types of tracepoints.  */
+
 int
-breakpoint_is_tracepoint (const struct breakpoint *b)
+is_tracepoint (const struct breakpoint *b)
 {
-  switch (b->type)
-    {
-    case bp_tracepoint:
-    case bp_fast_tracepoint:
-      return 1;
-    default:
-      return 0;
-
-    }
+  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
 }
-
+  
 /* A helper function that validsates that COMMANDS are valid for a
    breakpoint.  This function will throw an exception if a problem is
    found.  */
@@ -823,7 +840,7 @@ static void
 validate_commands_for_breakpoint (struct breakpoint *b,
                                  struct command_line *commands)
 {
-  if (breakpoint_is_tracepoint (b))
+  if (is_tracepoint (b))
     {
       /* We need to verify that each top-level element of commands
         is valid for tracepoints, that there's at most one while-stepping
@@ -894,9 +911,14 @@ struct commands_info
 {
   /* True if the command was typed at a tty.  */
   int from_tty;
+
+  /* The breakpoint range spec.  */
+  char *arg;
+
   /* Non-NULL if the body of the commands are being read from this
      already-parsed command.  */
   struct command_line *control;
+
   /* The command lines read from the user, or NULL if they have not
      yet been read.  */
   struct counted_command_line *cmd;
@@ -917,12 +939,23 @@ do_map_commands_command (struct breakpoint *b, void *data)
       if (info->control != NULL)
        l = copy_command_lines (info->control->body_list[0]);
       else
+       {
+         struct cleanup *old_chain;
+         char *str;
+
+         str = xstrprintf (_("Type commands for breakpoint(s) %s, one per line."),
+                           info->arg);
 
-       l = read_command_lines (_("Type commands for all specified breakpoints"),
-                               info->from_tty, 1,
-                               (breakpoint_is_tracepoint (b)
-                                ? check_tracepoint_command : 0),
-                               b);
+         old_chain = make_cleanup (xfree, str);
+
+         l = read_command_lines (str,
+                                 info->from_tty, 1,
+                                 (is_tracepoint (b)
+                                  ? check_tracepoint_command : 0),
+                                 b);
+
+         do_cleanups (old_chain);
+       }
 
       info->cmd = alloc_counted_command_line (l);
     }
@@ -955,12 +988,27 @@ commands_command_1 (char *arg, int from_tty, struct command_line *control)
 
   if (arg == NULL || !*arg)
     {
-      if (last_was_multi)
-       arg = xstrprintf ("%d-%d", multi_start, multi_end);
+      if (breakpoint_count - prev_breakpoint_count > 1)
+       arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, breakpoint_count);
       else if (breakpoint_count > 0)
        arg = xstrprintf ("%d", breakpoint_count);
-      make_cleanup (xfree, arg);
+      else
+       {
+         /* So that we don't try to free the incoming non-NULL
+            argument in the cleanup below.  Mapping breakpoint
+            numbers will fail in this case.  */
+         arg = NULL;
+       }
     }
+  else
+    /* The command loop has some static state, so we need to preserve
+       our argument.  */
+    arg = xstrdup (arg);
+
+  if (arg != NULL)
+    make_cleanup (xfree, arg);
+
+  info.arg = arg;
 
   map_breakpoint_numbers (arg, do_map_commands_command, &info);
 
@@ -1128,7 +1176,7 @@ insert_catchpoint (struct ui_out *uo, void *args)
 /* Return true if BPT is of any hardware watchpoint kind.  */
 
 static int
-is_hardware_watchpoint (struct breakpoint *bpt)
+is_hardware_watchpoint (const struct breakpoint *bpt)
 {
   return (bpt->type == bp_hardware_watchpoint
          || bpt->type == bp_read_watchpoint
@@ -1139,7 +1187,7 @@ is_hardware_watchpoint (struct breakpoint *bpt)
    software.  */
 
 static int
-is_watchpoint (struct breakpoint *bpt)
+is_watchpoint (const struct breakpoint *bpt)
 {
   return (is_hardware_watchpoint (bpt)
          || bpt->type == bp_watchpoint);
@@ -1542,7 +1590,7 @@ should_be_inserted (struct bp_location *bpt)
 
   /* Tracepoints are inserted by the target at a time of its choosing,
      not by us.  */
-  if (tracepoint_type (bpt->owner))
+  if (is_tracepoint (bpt->owner))
     return 0;
 
   return 1;
@@ -2916,36 +2964,6 @@ bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint)
   return NULL;
 }
 
-/* Find a step_resume breakpoint associated with this bpstat.
-   (If there are multiple step_resume bp's on the list, this function
-   will arbitrarily pick one.)
-
-   It is an error to use this function if BPSTAT doesn't contain a
-   step_resume breakpoint.
-
-   See wait_for_inferior's use of this function.  */
-struct breakpoint *
-bpstat_find_step_resume_breakpoint (bpstat bsp)
-{
-  int current_thread;
-
-  gdb_assert (bsp != NULL);
-
-  current_thread = pid_to_thread_id (inferior_ptid);
-
-  for (; bsp != NULL; bsp = bsp->next)
-    {
-      if ((bsp->breakpoint_at != NULL)
-         && (bsp->breakpoint_at->owner->type == bp_step_resume)
-         && (bsp->breakpoint_at->owner->thread == current_thread
-             || bsp->breakpoint_at->owner->thread == -1))
-       return bsp->breakpoint_at->owner;
-    }
-
-  internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found."));
-}
-
-
 /* Put in *NUM the breakpoint number of the first breakpoint we are stopped
    at.  *BSP upon return is a bpstat which points to the remaining
    breakpoints stopped at (but which is not guaranteed to be good for
@@ -3480,9 +3498,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
       /* We were not stopped by a watchpoint.  Mark all watchpoints
         as not triggered.  */
       ALL_BREAKPOINTS (b)
-       if (b->type == bp_hardware_watchpoint
-           || b->type == bp_read_watchpoint
-           || b->type == bp_access_watchpoint)
+       if (is_hardware_watchpoint (b))
          b->watchpoint_triggered = watch_triggered_no;
 
       return 0;
@@ -3493,9 +3509,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
       /* We were stopped by a watchpoint, but we don't know where.
         Mark all watchpoints as unknown.  */
       ALL_BREAKPOINTS (b)
-       if (b->type == bp_hardware_watchpoint
-           || b->type == bp_read_watchpoint
-           || b->type == bp_access_watchpoint)
+       if (is_hardware_watchpoint (b))
          b->watchpoint_triggered = watch_triggered_unknown;
 
       return stopped_by_watchpoint;
@@ -3506,9 +3520,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
      triggered.  */
 
   ALL_BREAKPOINTS (b)
-    if (b->type == bp_hardware_watchpoint
-       || b->type == bp_read_watchpoint
-       || b->type == bp_access_watchpoint)
+    if (is_hardware_watchpoint (b))
       {
        struct bp_location *loc;
        struct value *v;
@@ -3686,13 +3698,10 @@ bpstat_check_location (const struct bp_location *bl,
 
   /* By definition, the inferior does not report stops at
      tracepoints.  */
-  if (tracepoint_type (b))
+  if (is_tracepoint (b))
     return 0;
 
-  if (b->type != bp_watchpoint
-      && b->type != bp_hardware_watchpoint
-      && b->type != bp_read_watchpoint
-      && b->type != bp_access_watchpoint
+  if (!is_watchpoint (b)
       && b->type != bp_hardware_breakpoint
       && b->type != bp_catchpoint)     /* a non-watchpoint bp */
     {
@@ -3704,17 +3713,15 @@ bpstat_check_location (const struct bp_location *bl,
          && !section_is_mapped (bl->section))
        return 0;
     }
-  
+
   /* Continuable hardware watchpoints are treated as non-existent if the
      reason we stopped wasn't a hardware watchpoint (we didn't stop on
      some data address).  Otherwise gdb won't stop on a break instruction
      in the code (not from a breakpoint) when a hardware watchpoint has
      been defined.  Also skip watchpoints which we know did not trigger
      (did not match the data address).  */
-  
-  if ((b->type == bp_hardware_watchpoint
-       || b->type == bp_read_watchpoint
-       || b->type == bp_access_watchpoint)
+
+  if (is_hardware_watchpoint (b)
       && b->watchpoint_triggered == watch_triggered_no)
     return 0;
   
@@ -3747,10 +3754,7 @@ bpstat_check_watchpoint (bpstat bs)
   const struct bp_location *bl = bs->breakpoint_at;
   struct breakpoint *b = bl->owner;
 
-  if (b->type == bp_watchpoint
-      || b->type == bp_read_watchpoint
-      || b->type == bp_access_watchpoint
-      || b->type == bp_hardware_watchpoint)
+  if (is_watchpoint (b))
     {
       CORE_ADDR addr;
       struct value *v;
@@ -4049,9 +4053,9 @@ bpstat_stop_status (struct address_space *aspace,
       for (bl = b->loc; bl != NULL; bl = bl->next)
        {
          /* For hardware watchpoints, we look only at the first location.
-            The watchpoint_check function will work on entire expression,
-            not the individual locations.  For read watchopints, the
-            watchpoints_triggered function have checked all locations
+            The watchpoint_check function will work on the entire expression,
+            not the individual locations.  For read watchpoints, the
+            watchpoints_triggered function has checked all locations
             already.  */
          if (b->type == bp_hardware_watchpoint && bl != b->loc)
            break;
@@ -4136,12 +4140,8 @@ bpstat_stop_status (struct address_space *aspace,
      not have changed, but the intermediate memory locations we are
      watching may have.  Don't bother if we're stopping; this will get
      done later.  */
-  for (bs = root_bs->next; bs != NULL; bs = bs->next)
-    if (bs->stop)
-      break;
-
   need_remove_insert = 0;
-  if (bs == NULL)
+  if (! bpstat_causes_stop (root_bs->next))
     for (bs = root_bs->next; bs != NULL; bs = bs->next)
       if (!bs->stop
          && bs->breakpoint_at->owner
@@ -4741,7 +4741,7 @@ print_one_breakpoint_location (struct breakpoint *b,
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
-      if (tracepoint_type (b))
+      if (is_tracepoint (b))
        ui_out_text (uiout, "\ttrace only if ");
       else
        ui_out_text (uiout, "\tstop only if ");
@@ -4921,19 +4921,19 @@ user_settable_breakpoint (const struct breakpoint *b)
   return (b->type == bp_breakpoint
          || b->type == bp_catchpoint
          || b->type == bp_hardware_breakpoint
-         || tracepoint_type (b)
-         || b->type == bp_watchpoint
-         || b->type == bp_read_watchpoint
-         || b->type == bp_access_watchpoint
-         || b->type == bp_hardware_watchpoint);
+         || is_tracepoint (b)
+         || is_watchpoint (b));
 }
        
 /* Print information on user settable breakpoint (watchpoint, etc)
-   number BNUM.  If BNUM is -1 print all user settable breakpoints.
-   If ALLFLAG is non-zero, include non- user settable breakpoints. */
+   number BNUM.  If BNUM is -1 print all user-settable breakpoints.
+   If ALLFLAG is non-zero, include non-user-settable breakpoints.  If
+   FILTER is non-NULL, call it on each breakpoint and only include the
+   ones for which it returns non-zero.  Return the total number of
+   breakpoints listed.  */
 
-static void
-breakpoint_1 (int bnum, int allflag)
+static int
+breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
 {
   struct breakpoint *b;
   struct bp_location *last_loc = NULL;
@@ -4951,6 +4951,10 @@ breakpoint_1 (int bnum, int allflag)
     if (bnum == -1
        || bnum == b->number)
       {
+       /* If we have a filter, only list the breakpoints it accepts.  */
+       if (filter && !filter (b))
+         continue;
+       
        if (allflag || user_settable_breakpoint (b))
          {
            int addr_bit = breakpoint_address_bits (b);
@@ -5006,6 +5010,10 @@ breakpoint_1 (int bnum, int allflag)
     if (bnum == -1
        || bnum == b->number)
       {
+       /* If we have a filter, only list the breakpoints it accepts.  */
+       if (filter && !filter (b))
+         continue;
+       
        /* We only print out user settable breakpoints unless the
           allflag is set. */
        if (allflag || user_settable_breakpoint (b))
@@ -5017,11 +5025,15 @@ breakpoint_1 (int bnum, int allflag)
 
   if (nr_printable_breakpoints == 0)
     {
-      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);
+      /* If there's a filter, let the caller decide how to report empty list.  */
+      if (!filter)
+       {
+         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
     {
@@ -5032,8 +5044,29 @@ breakpoint_1 (int bnum, int allflag)
   /* FIXME? Should this be moved up so that it is only called when
      there have been breakpoints? */
   annotate_breakpoints_table_end ();
+
+  return nr_printable_breakpoints;
 }
 
+/* Display the value of default-collect in a way that is generally
+   compatible with the breakpoint list.  */
+
+static void
+default_collect_info (void)
+{
+  /* If it has no value (which is frequently the case), say nothing; a
+     message like "No default-collect." gets in user's face when it's
+     not wanted.  */
+  if (!*default_collect)
+    return;
+
+  /* The following phrase lines up nicely with per-tracepoint collect
+     actions.  */
+  ui_out_text (uiout, "default collect ");
+  ui_out_field_string (uiout, "default-collect", default_collect);
+  ui_out_text (uiout, " \n");
+}
+  
 static void
 breakpoints_info (char *bnum_exp, int from_tty)
 {
@@ -5042,7 +5075,28 @@ breakpoints_info (char *bnum_exp, int from_tty)
   if (bnum_exp)
     bnum = parse_and_eval_long (bnum_exp);
 
-  breakpoint_1 (bnum, 0);
+  breakpoint_1 (bnum, 0, NULL);
+
+  default_collect_info ();
+}
+
+static void
+watchpoints_info (char *wpnum_exp, int from_tty)
+{
+  int wpnum = -1, num_printed;
+
+  if (wpnum_exp)
+    wpnum = parse_and_eval_long (wpnum_exp);
+
+  num_printed = breakpoint_1 (wpnum, 0, is_watchpoint);
+
+  if (num_printed == 0)
+    {
+      if (wpnum == -1)
+       ui_out_message (uiout, 0, "No watchpoints.\n");
+      else
+       ui_out_message (uiout, 0, "No watchpoint number %d.\n", wpnum);
+    }
 }
 
 static void
@@ -5053,7 +5107,9 @@ maintenance_info_breakpoints (char *bnum_exp, int from_tty)
   if (bnum_exp)
     bnum = parse_and_eval_long (bnum_exp);
 
-  breakpoint_1 (bnum, 1);
+  breakpoint_1 (bnum, 1, NULL);
+
+  default_collect_info ();
 }
 
 static int
@@ -5382,7 +5438,7 @@ set_breakpoint_location_function (struct bp_location *loc)
 {
   if (loc->owner->type == bp_breakpoint
       || loc->owner->type == bp_hardware_breakpoint
-      || tracepoint_type (loc->owner))
+      || is_tracepoint (loc->owner))
     {
       find_pc_partial_function (loc->address, &(loc->function_name), 
                                NULL, NULL);
@@ -5669,7 +5725,7 @@ disable_breakpoints_in_shlibs (void)
     if (((b->type == bp_breakpoint)
         || (b->type == bp_jit_event)
         || (b->type == bp_hardware_breakpoint)
-        || (tracepoint_type (b)))
+        || (is_tracepoint (b)))
        && loc->pspace == current_program_space
        && !loc->shlib_disabled
 #ifdef PC_SOLIB
@@ -5801,6 +5857,15 @@ print_mention_catch_fork (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (fork)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for fork
+   catchpoints.  */
+
+static void
+print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch fork");
+}
+
 /* The breakpoint_ops structure to be used in fork catchpoints.  */
 
 static struct breakpoint_ops catch_fork_breakpoint_ops =
@@ -5810,7 +5875,8 @@ static struct breakpoint_ops catch_fork_breakpoint_ops =
   breakpoint_hit_catch_fork,
   print_it_catch_fork,
   print_one_catch_fork,
-  print_mention_catch_fork
+  print_mention_catch_fork,
+  print_recreate_catch_fork
 };
 
 /* Implement the "insert" breakpoint_ops method for vfork catchpoints.  */
@@ -5882,6 +5948,15 @@ print_mention_catch_vfork (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (vfork)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for vfork
+   catchpoints.  */
+
+static void
+print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch vfork");
+}
+
 /* The breakpoint_ops structure to be used in vfork catchpoints.  */
 
 static struct breakpoint_ops catch_vfork_breakpoint_ops =
@@ -5891,7 +5966,8 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops =
   breakpoint_hit_catch_vfork,
   print_it_catch_vfork,
   print_one_catch_vfork,
-  print_mention_catch_vfork
+  print_mention_catch_vfork,
+  print_recreate_catch_vfork
 };
 
 /* Implement the "insert" breakpoint_ops method for syscall
@@ -6130,6 +6206,33 @@ print_mention_catch_syscall (struct breakpoint *b)
                      b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static void
+print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch syscall");
+
+  if (b->syscalls_to_be_caught)
+    {
+      int i, iter;
+
+      for (i = 0;
+           VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
+           i++)
+        {
+          struct syscall s;
+
+          get_syscall_by_number (iter, &s);
+          if (s.name)
+            fprintf_unfiltered (fp, " %s", s.name);
+          else
+            fprintf_unfiltered (fp, " %d", s.number);
+        }
+    }
+}
+
 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
 
 static struct breakpoint_ops catch_syscall_breakpoint_ops =
@@ -6139,7 +6242,8 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops =
   breakpoint_hit_catch_syscall,
   print_it_catch_syscall,
   print_one_catch_syscall,
-  print_mention_catch_syscall
+  print_mention_catch_syscall,
+  print_recreate_catch_syscall
 };
 
 /* Returns non-zero if 'b' is a syscall catchpoint.  */
@@ -6275,6 +6379,15 @@ print_mention_catch_exec (struct breakpoint *b)
   printf_filtered (_("Catchpoint %d (exec)"), b->number);
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for exec
+   catchpoints.  */
+
+static void
+print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
+{
+  fprintf_unfiltered (fp, "catch exec");
+}
+
 static struct breakpoint_ops catch_exec_breakpoint_ops =
 {
   insert_catch_exec,
@@ -6282,7 +6395,8 @@ static struct breakpoint_ops catch_exec_breakpoint_ops =
   breakpoint_hit_catch_exec,
   print_it_catch_exec,
   print_one_catch_exec,
-  print_mention_catch_exec
+  print_mention_catch_exec,
+  print_recreate_catch_exec
 };
 
 static void
@@ -6329,9 +6443,7 @@ hw_watchpoint_used_count (enum bptype type, int *other_type_used)
       {
        if (b->type == type)
          i++;
-       else if ((b->type == bp_hardware_watchpoint
-                 || b->type == bp_read_watchpoint
-                 || b->type == bp_access_watchpoint))
+       else if (is_hardware_watchpoint (b))
          *other_type_used = 1;
       }
   }
@@ -6345,11 +6457,7 @@ disable_watchpoints_before_interactive_call_start (void)
 
   ALL_BREAKPOINTS (b)
   {
-    if (((b->type == bp_watchpoint)
-        || (b->type == bp_hardware_watchpoint)
-        || (b->type == bp_read_watchpoint)
-        || (b->type == bp_access_watchpoint))
-       && breakpoint_enabled (b))
+    if (is_watchpoint (b) && breakpoint_enabled (b))
       {
        b->enable_state = bp_call_disabled;
        update_global_location_list (0);
@@ -6364,11 +6472,7 @@ enable_watchpoints_after_interactive_call_stop (void)
 
   ALL_BREAKPOINTS (b)
   {
-    if (((b->type == bp_watchpoint)
-        || (b->type == bp_hardware_watchpoint)
-        || (b->type == bp_read_watchpoint)
-        || (b->type == bp_access_watchpoint))
-       && (b->enable_state == bp_call_disabled))
+    if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
       {
        b->enable_state = bp_enabled;
        update_global_location_list (1);
@@ -7235,7 +7339,7 @@ create_breakpoint (struct gdbarch *gdbarch,
   int not_found = 0;
   enum bptype type_wanted;
   int task = 0;
-  int first_bp_set = breakpoint_count + 1;
+  int prev_bkpt_count = breakpoint_count;
 
   sals.sals = NULL;
   sals.nelts = 0;
@@ -7395,9 +7499,7 @@ create_breakpoint (struct gdbarch *gdbarch,
     {
       warning (_("Multiple breakpoints were set.\n"
                 "Use the \"delete\" command to delete unwanted breakpoints."));
-      multi_start = first_bp_set;
-      multi_end = breakpoint_count;
-      last_was_multi = 1;
+      prev_breakpoint_count = prev_bkpt_count;
     }
 
   /* That's it.  Discard the cleanups for data inserted into the
@@ -8244,13 +8346,29 @@ print_mention_exception_catchpoint (struct breakpoint *b)
                               : _(" (catch)"));
 }
 
+/* Implement the "print_recreate" breakpoint_ops method for throw and
+   catch catchpoints.  */
+
+static void
+print_recreate_exception_catchpoint (struct breakpoint *b, struct ui_file *fp)
+{
+  int bp_temp;
+  int bp_throw;
+
+  bp_temp = b->disposition == disp_del;
+  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
+  fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
+}
+
 static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
   NULL, /* insert */
   NULL, /* remove */
   NULL, /* breakpoint_hit */
   print_exception_catchpoint,
   print_one_exception_catchpoint,
-  print_mention_exception_catchpoint
+  print_mention_exception_catchpoint,
+  print_recreate_exception_catchpoint
 };
 
 static int
@@ -8613,11 +8731,7 @@ clear_command (char *arg, int from_tty)
        {
          int match = 0;
          /* Are we going to delete b? */
-         if (b->type != bp_none
-             && b->type != bp_watchpoint
-             && b->type != bp_hardware_watchpoint
-             && b->type != bp_read_watchpoint
-             && b->type != bp_access_watchpoint)
+         if (b->type != bp_none && !is_watchpoint (b))
            {
              struct bp_location *loc = b->loc;
              for (; loc; loc = loc->next)
@@ -9027,7 +9141,7 @@ update_global_location_list (int should_insert)
          || !loc->enabled
          || loc->shlib_disabled
          || !breakpoint_address_is_meaningful (b)
-         || tracepoint_type (b))
+         || is_tracepoint (b))
        continue;
 
       /* Permanent breakpoint should always be inserted.  */
@@ -9687,6 +9801,14 @@ set_ignore_count (int bptnum, int count, int from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bptnum)
     {
+      if (is_tracepoint (b))
+       {
+         if (from_tty && count != 0)
+           printf_filtered (_("Ignore count ignored for tracepoint %d."),
+                            bptnum);
+         return;
+       }
+      
       b->ignore_count = count;
       if (from_tty)
        {
@@ -9915,10 +10037,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
        error (_("Hardware breakpoints used exceeds limit."));
     }
 
-  if (bpt->type == bp_watchpoint
-      || bpt->type == bp_hardware_watchpoint
-      || bpt->type == bp_read_watchpoint
-      || bpt->type == bp_access_watchpoint)
+  if (is_watchpoint (bpt))
     {
       struct gdb_exception e;
 
@@ -10301,6 +10420,24 @@ ftrace_command (char *arg, int from_tty)
     set_tracepoint_count (breakpoint_count);
 }
 
+/* Set up a fake reader function that gets command lines from a linked
+   list that was acquired during tracepoint uploading.  */
+
+static struct uploaded_tp *this_utp;
+static int next_cmd;
+
+static char *
+read_uploaded_action (void)
+{
+  char *rslt;
+
+  VEC_iterate (char_ptr, this_utp->cmd_strings, next_cmd, rslt);
+
+  next_cmd++;
+
+  return rslt;
+}
+
 /* Given information about a tracepoint as recorded on a target (which
    can be either a live system or a trace file), attempt to create an
    equivalent GDB tracepoint.  This is not a reliable process, since
@@ -10310,15 +10447,31 @@ ftrace_command (char *arg, int from_tty)
 struct breakpoint *
 create_tracepoint_from_upload (struct uploaded_tp *utp)
 {
-  char buf[100];
+  char *addr_str, small_buf[100];
   struct breakpoint *tp;
 
-  /* In the absence of a source location, fall back to raw address.  */
-  sprintf (buf, "*%s", paddress (get_current_arch(), utp->addr));
+  if (utp->at_string)
+    addr_str = utp->at_string;
+  else
+    {
+      /* In the absence of a source location, fall back to raw
+        address.  Since there is no way to confirm that the address
+        means the same thing as when the trace was started, warn the
+        user.  */
+      warning (_("Uploaded tracepoint %d has no source location, using raw address"),
+              utp->number);
+      sprintf (small_buf, "*%s", hex_string (utp->addr));
+      addr_str = small_buf;
+    }
+
+  /* There's not much we can do with a sequence of bytecodes.  */
+  if (utp->cond && !utp->cond_string)
+    warning (_("Uploaded tracepoint %d condition has no source form, ignoring it"),
+            utp->number);
 
   if (!create_breakpoint (get_current_arch (),
-                         buf,
-                         NULL, 0, 1 /* parse arg */,
+                         addr_str,
+                         utp->cond_string, -1, 0 /* parse cond/thread */,
                          0 /* tempflag */,
                          (utp->type == bp_fast_tracepoint) /* hardwareflag */,
                          1 /* traceflag */,
@@ -10331,30 +10484,36 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
 
   set_tracepoint_count (breakpoint_count);
   
+  /* Get the tracepoint we just created.  */
   tp = get_tracepoint (tracepoint_count);
   gdb_assert (tp != NULL);
 
   if (utp->pass > 0)
     {
-      sprintf (buf, "%d %d", utp->pass, tp->number);
+      sprintf (small_buf, "%d %d", utp->pass, tp->number);
 
-      trace_pass_command (buf, 0);
+      trace_pass_command (small_buf, 0);
     }
 
-  if (utp->cond)
+  /* If we have uploaded versions of the original commands, set up a
+     special-purpose "reader" function and call the usual command line
+     reader, then pass the result to the breakpoint command-setting
+     function.  */
+  if (!VEC_empty (char_ptr, utp->cmd_strings))
     {
-      printf_filtered ("Want to restore a condition\n");
-    }
+      struct command_line *cmd_list;
 
-  if (utp->numactions > 0)
-    {
-      printf_filtered ("Want to restore action list\n");
-    }
+      this_utp = utp;
+      next_cmd = 0;
 
-  if (utp->num_step_actions > 0)
-    {
-      printf_filtered ("Want to restore action list\n");
+      cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
+
+      breakpoint_set_commands (tp, cmd_list);
     }
+  else if (!VEC_empty (char_ptr, utp->actions)
+          || !VEC_empty (char_ptr, utp->step_actions))
+    warning (_("Uploaded tracepoint %d actions have no source form, ignoring them"),
+            utp->number);
 
   return tp;
   }
@@ -10365,29 +10524,22 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
 static void
 tracepoints_info (char *tpnum_exp, int from_tty)
 {
-  struct breakpoint *b;
-  int tps_to_list = 0;
+  int tpnum = -1, num_printed;
+
+  if (tpnum_exp)
+    tpnum = parse_and_eval_long (tpnum_exp);
+
+  num_printed = breakpoint_1 (tpnum, 0, is_tracepoint);
 
-  /* In the no-arguments case, say "No tracepoints" if none found.  */
-  if (tpnum_exp == 0)
+  if (num_printed == 0)
     {
-      ALL_TRACEPOINTS (b)
-      {
-       if (b->number >= 0)
-         {
-           tps_to_list = 1;
-           break;
-         }
-      }
-      if (!tps_to_list)
-       {
-         ui_out_message (uiout, 0, "No tracepoints.\n");
-         return;
-       }
+      if (tpnum == -1)
+       ui_out_message (uiout, 0, "No tracepoints.\n");
+      else
+       ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum);
     }
 
-  /* Otherwise be the same as "info break".  */
-  breakpoints_info (tpnum_exp, from_tty);
+  default_collect_info ();
 }
 
 /* The 'enable trace' command enables tracepoints.  
@@ -10436,7 +10588,7 @@ delete_trace_command (char *arg, int from_tty)
        {
          ALL_BREAKPOINTS_SAFE (b, temp)
          {
-           if (tracepoint_type (b)
+           if (is_tracepoint (b)
                && b->number >= 0)
              delete_breakpoint (b);
          }
@@ -10570,51 +10722,134 @@ get_tracepoint_by_number (char **arg, int multi_p, int optional_p)
   return NULL;
 }
 
-/* save-tracepoints command */
+/* Save information on user settable breakpoints (watchpoints, etc) to
+   a new script file named FILENAME.  If FILTER is non-NULL, call it
+   on each breakpoint and only include the ones for which it returns
+   non-zero.  */
+
 static void
-tracepoint_save_command (char *args, int from_tty)
+save_breakpoints (char *filename, int from_tty,
+                 int (*filter) (const struct breakpoint *))
 {
   struct breakpoint *tp;
-  int any_tp = 0;
-  struct command_line *line;
+  int any = 0;
   char *pathname;
-  char tmp[40];
   struct cleanup *cleanup;
   struct ui_file *fp;
+  int extra_trace_bits = 0;
 
-  if (args == 0 || *args == 0)
-    error (_("Argument required (file name in which to save tracepoints)"));
+  if (filename == 0 || *filename == 0)
+    error (_("Argument required (file name in which to save)"));
 
   /* See if we have anything to save.  */
-  ALL_TRACEPOINTS (tp)
+  ALL_BREAKPOINTS (tp)
   {
-    any_tp = 1;
-    break;
+    /* Skip internal and momentary breakpoints.  */
+    if (!user_settable_breakpoint (tp))
+      continue;
+
+    /* If we have a filter, only save the breakpoints it accepts.  */
+    if (filter && !filter (tp))
+      continue;
+
+    any = 1;
+
+    if (is_tracepoint (tp))
+      {
+       extra_trace_bits = 1;
+
+       /* We can stop searching.  */
+       break;
+      }
   }
-  if (!any_tp)
+
+  if (!any)
     {
-      warning (_("save-tracepoints: no tracepoints to save."));
+      warning (_("Nothing to save."));
       return;
     }
 
-  pathname = tilde_expand (args);
+  pathname = tilde_expand (filename);
   cleanup = make_cleanup (xfree, pathname);
   fp = gdb_fopen (pathname, "w");
   if (!fp)
-    error (_("Unable to open file '%s' for saving tracepoints (%s)"),
-          args, safe_strerror (errno));
+    error (_("Unable to open file '%s' for saving (%s)"),
+          filename, safe_strerror (errno));
   make_cleanup_ui_file_delete (fp);
-  
-  ALL_TRACEPOINTS (tp)
+
+  if (extra_trace_bits)
+    save_trace_state_variables (fp);
+
+  ALL_BREAKPOINTS (tp)
   {
-    if (tp->addr_string)
-      fprintf_unfiltered (fp, "trace %s\n", tp->addr_string);
+    /* Skip internal and momentary breakpoints.  */
+    if (!user_settable_breakpoint (tp))
+      continue;
+
+    /* If we have a filter, only save the breakpoints it accepts.  */
+    if (filter && !filter (tp))
+      continue;
+
+    if (tp->ops != NULL)
+      (tp->ops->print_recreate) (tp, fp);
     else
       {
-       sprintf_vma (tmp, tp->loc->address);
-       fprintf_unfiltered (fp, "trace *0x%s\n", tmp);
+       if (tp->type == bp_fast_tracepoint)
+         fprintf_unfiltered (fp, "ftrace");
+       else if (tp->type == bp_tracepoint)
+         fprintf_unfiltered (fp, "trace");
+       else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
+         fprintf_unfiltered (fp, "tbreak");
+       else if (tp->type == bp_breakpoint)
+         fprintf_unfiltered (fp, "break");
+       else if (tp->type == bp_hardware_breakpoint
+                && tp->disposition == disp_del)
+         fprintf_unfiltered (fp, "thbreak");
+       else if (tp->type == bp_hardware_breakpoint)
+         fprintf_unfiltered (fp, "hbreak");
+       else if (tp->type == bp_watchpoint)
+         fprintf_unfiltered (fp, "watch");
+       else if (tp->type == bp_hardware_watchpoint)
+         fprintf_unfiltered (fp, "watch");
+       else if (tp->type == bp_read_watchpoint)
+         fprintf_unfiltered (fp, "rwatch");
+       else if (tp->type == bp_access_watchpoint)
+         fprintf_unfiltered (fp, "awatch");
+       else
+         internal_error (__FILE__, __LINE__,
+                         _("unhandled breakpoint type %d"), (int) tp->type);
+
+       if (tp->exp_string)
+         fprintf_unfiltered (fp, " %s", tp->exp_string);
+       else if (tp->addr_string)
+         fprintf_unfiltered (fp, " %s", tp->addr_string);
+       else
+         {
+           char tmp[40];
+
+           sprintf_vma (tmp, tp->loc->address);
+           fprintf_unfiltered (fp, " *0x%s", tmp);
+         }
       }
 
+    if (tp->thread != -1)
+      fprintf_unfiltered (fp, " thread %d", tp->thread);
+
+    if (tp->task != 0)
+      fprintf_unfiltered (fp, " task %d", tp->task);
+
+    fprintf_unfiltered (fp, "\n");
+
+    /* Note, we can't rely on tp->number for anything, as we can't
+       assume the recreated breakpoint numbers will match.  Use $bpnum
+       instead.  */
+
+    if (tp->cond_string)
+      fprintf_unfiltered (fp, "  condition $bpnum %s\n", tp->cond_string);
+
+    if (tp->ignore_count)
+      fprintf_unfiltered (fp, "  ignore $bpnum %d\n", tp->ignore_count);
+
     if (tp->pass_count)
       fprintf_unfiltered (fp, "  passcount %d\n", tp->pass_count);
 
@@ -10622,7 +10857,7 @@ tracepoint_save_command (char *args, int from_tty)
       {
        volatile struct gdb_exception ex;       
 
-       fprintf_unfiltered (fp, "  actions\n");
+       fprintf_unfiltered (fp, "  commands\n");
        
        ui_out_redirect (uiout, fp);
        TRY_CATCH (ex, RETURN_MASK_ERROR)
@@ -10636,11 +10871,46 @@ tracepoint_save_command (char *args, int from_tty)
 
        fprintf_unfiltered (fp, "  end\n");
       }
+
+    if (tp->enable_state == bp_disabled)
+      fprintf_unfiltered (fp, "disable\n");
+
+    /* If this is a multi-location breakpoint, check if the locations
+       should be individually disabled.  Watchpoint locations are
+       special, and not user visible.  */
+    if (!is_watchpoint (tp) && tp->loc && tp->loc->next)
+      {
+       struct bp_location *loc;
+       int n = 1;
+
+       for (loc = tp->loc; loc != NULL; loc = loc->next, n++)
+         if (!loc->enabled)
+           fprintf_unfiltered (fp, "disable $bpnum.%d\n", n);
+      }
   }
+
+  if (extra_trace_bits && *default_collect)
+    fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
+
   do_cleanups (cleanup);
   if (from_tty)
-    printf_filtered (_("Tracepoints saved to file '%s'.\n"), args);
-  return;
+    printf_filtered (_("Saved to file '%s'.\n"), filename);
+}
+
+/* The `save breakpoints' command.  */
+
+static void
+save_breakpoints_command (char *args, int from_tty)
+{
+  save_breakpoints (args, from_tty, NULL);
+}
+
+/* The `save tracepoints' command.  */
+
+static void
+save_tracepoints_command (char *args, int from_tty)
+{
+  save_breakpoints (args, from_tty, is_tracepoint);
 }
 
 /* Create a vector of all tracepoints.  */
@@ -10719,11 +10989,17 @@ clear_syscall_counts (struct inferior *inf)
   VEC_free (int, inf->syscalls_counts);
 }
 
+static void
+save_command (char *arg, int from_tty)
+{
+  printf_unfiltered (_("\
+\"save\" must be followed by the name of a save subcommand.\n"));
+  help_list (save_cmdlist, "save ", -1, gdb_stdout);
+}
+
 void
 _initialize_breakpoint (void)
 {
-  static struct cmd_list_element *breakpoint_set_cmdlist;
-  static struct cmd_list_element *breakpoint_show_cmdlist;
   struct cmd_list_element *c;
 
   observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
@@ -11062,8 +11338,9 @@ A watchpoint stops execution of your program whenever the value of\n\
 an expression is either read or written."));
   set_cmd_completer (c, expression_completer);
 
-  add_info ("watchpoints", breakpoints_info,
-           _("Synonym for ``info breakpoints''."));
+  add_info ("watchpoints", watchpoints_info, _("\
+Status of watchpoints, or watchpoint number NUMBER."));
+
 
 
   /* XXX: cagney/2005-02-23: This should be a boolean, and should
@@ -11136,11 +11413,28 @@ The trace will end when the tracepoint has been passed 'count' times.\n\
 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
 if TPNUM is omitted, passcount refers to the last tracepoint defined."));
 
-  c = add_com ("save-tracepoints", class_trace, tracepoint_save_command, _("\
+  add_prefix_cmd ("save", class_breakpoint, save_command,
+                 _("Save breakpoint definitions as a script."),
+                 &save_cmdlist, "save ",
+                 0/*allow-unknown*/, &cmdlist);
+
+  c = add_cmd ("breakpoints", class_breakpoint, save_breakpoints_command, _("\
+Save current breakpoint definitions as a script.\n\
+This includes all types of breakpoints (breakpoints, watchpoints, \n\
+catchpoints, tracepoints).  Use the 'source' command in another debug\n\
+session to restore them."),
+              &save_cmdlist);
+  set_cmd_completer (c, filename_completer);
+
+  c = add_cmd ("tracepoints", class_trace, save_tracepoints_command, _("\
 Save current tracepoint definitions as a script.\n\
-Use the 'source' command in another debug session to restore them."));
+Use the 'source' command in another debug session to restore them."),
+              &save_cmdlist);
   set_cmd_completer (c, filename_completer);
 
+  c = add_com_alias ("save-tracepoints", "save tracepoints", class_trace, 0);
+  deprecate_cmd (c, "save tracepoints");
+
   add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
 Breakpoint specific settings\n\
 Configure various breakpoint-specific variables such as\n\
This page took 0.048551 seconds and 4 git commands to generate.