Introduce command_line_up
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-break.c
index 245cf4489b151a9723276afd86229bc8cb44c21b..cfe2d34f23fdd9823a025d82bd4c405d258f92aa 100644 (file)
@@ -1,6 +1,5 @@
 /* MI Command Set - breakpoint and watchpoint commands.
 /* MI Command Set - breakpoint and watchpoint commands.
-   Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2000-2017 Free Software Foundation, Inc.
    Contributed by Cygnus Solutions (a Red Hat company).
 
    This file is part of GDB.
    Contributed by Cygnus Solutions (a Red Hat company).
 
    This file is part of GDB.
 #include "ui-out.h"
 #include "mi-out.h"
 #include "breakpoint.h"
 #include "ui-out.h"
 #include "mi-out.h"
 #include "breakpoint.h"
-#include "gdb_string.h"
 #include "mi-getopt.h"
 #include "gdb.h"
 #include "mi-getopt.h"
 #include "gdb.h"
-#include "exceptions.h"
 #include "observer.h"
 #include "observer.h"
+#include "mi-main.h"
+#include "mi-cmd-break.h"
+#include "language.h"
+#include "location.h"
+#include "linespec.h"
+#include "gdb_obstack.h"
+#include <ctype.h>
 
 enum
   {
 
 enum
   {
@@ -43,13 +47,13 @@ static int mi_breakpoint_observers_installed;
 
 static int mi_can_breakpoint_notify;
 
 
 static int mi_can_breakpoint_notify;
 
-/* Output a single breakpoint, when allowed. */
+/* Output a single breakpoint, when allowed.  */
 
 static void
 
 static void
-breakpoint_notify (int b)
+breakpoint_notify (struct breakpoint *b)
 {
   if (mi_can_breakpoint_notify)
 {
   if (mi_can_breakpoint_notify)
-    gdb_breakpoint_query (uiout, b, NULL);
+    gdb_breakpoint_query (current_uiout, b->number, NULL);
 }
 
 enum bp_type
 }
 
 enum bp_type
@@ -59,11 +63,111 @@ enum bp_type
     REGEXP_BP
   };
 
     REGEXP_BP
   };
 
-/* Implements the -break-insert command.
-   See the MI manual for the list of possible options.  */
+/* Arrange for all new breakpoints and catchpoints to be reported to
+   CURRENT_UIOUT until the cleanup returned by this function is run.
 
 
-void
-mi_cmd_break_insert (char *command, char **argv, int argc)
+   Note that MI output will be probably invalid if more than one
+   breakpoint is created inside one MI command.  */
+
+struct cleanup *
+setup_breakpoint_reporting (void)
+{
+  struct cleanup *rev_flag;
+
+  if (! mi_breakpoint_observers_installed)
+    {
+      observer_attach_breakpoint_created (breakpoint_notify);
+      mi_breakpoint_observers_installed = 1;
+    }
+
+  rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
+  mi_can_breakpoint_notify = 1;
+
+  return rev_flag;
+}
+
+
+/* Convert arguments in ARGV to the string in "format",argv,argv...
+   and return it.  */
+
+static char *
+mi_argv_to_format (char **argv, int argc)
+{
+  int i;
+  struct obstack obstack;
+  char *ret;
+
+  obstack_init (&obstack);
+
+  /* Convert ARGV[OIND + 1] to format string and save to FORMAT.  */
+  obstack_1grow (&obstack, '\"');
+  for (i = 0; i < strlen (argv[0]); i++)
+    {
+      switch (argv[0][i])
+       {
+       case '\\':
+         obstack_grow (&obstack, "\\\\", 2);
+         break;
+       case '\a':
+         obstack_grow (&obstack, "\\a", 2);
+         break;
+       case '\b':
+         obstack_grow (&obstack, "\\b", 2);
+         break;
+       case '\f':
+         obstack_grow (&obstack, "\\f", 2);
+         break;
+       case '\n':
+         obstack_grow (&obstack, "\\n", 2);
+         break;
+       case '\r':
+         obstack_grow (&obstack, "\\r", 2);
+         break;
+       case '\t':
+         obstack_grow (&obstack, "\\t", 2);
+         break;
+       case '\v':
+         obstack_grow (&obstack, "\\v", 2);
+         break;
+       case '"':
+         obstack_grow (&obstack, "\\\"", 2);
+         break;
+       default:
+         if (isprint (argv[0][i]))
+           obstack_grow (&obstack, argv[0] + i, 1);
+         else
+           {
+             char tmp[5];
+
+             xsnprintf (tmp, sizeof (tmp), "\\%o",
+                        (unsigned char) argv[0][i]);
+             obstack_grow (&obstack, tmp, strlen (tmp));
+           }
+         break;
+       }
+    }
+  obstack_1grow (&obstack, '\"');
+
+  /* Apply other argv to FORMAT.  */
+  for (i = 1; i < argc; i++)
+    {
+      obstack_1grow (&obstack, ',');
+      obstack_grow (&obstack, argv[i], strlen (argv[i]));
+    }
+  obstack_1grow (&obstack, '\0');
+
+  ret = xstrdup ((const char *) obstack_finish (&obstack));
+  obstack_free (&obstack, NULL);
+
+  return ret;
+}
+
+/* Insert breakpoint.
+   If dprintf is true, it will insert dprintf.
+   If not, it will insert other type breakpoint.  */
+
+static void
+mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
 {
   char *address = NULL;
   int hardware = 0;
 {
   char *address = NULL;
   int hardware = 0;
@@ -74,16 +178,23 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
   int pending = 0;
   int enabled = 1;
   int tracepoint = 0;
   int pending = 0;
   int enabled = 1;
   int tracepoint = 0;
-  struct cleanup *back_to;
+  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
   enum bptype type_wanted;
   enum bptype type_wanted;
+  event_location_up location;
+  struct breakpoint_ops *ops;
+  int is_explicit = 0;
+  struct explicit_location explicit_loc;
+  char *extra_string = NULL;
 
   enum opt
     {
       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
       TRACEPOINT_OPT,
 
   enum opt
     {
       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
       TRACEPOINT_OPT,
+      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
+      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
     };
     };
-  static struct mi_opt opts[] =
+  static const struct mi_opt opts[] =
   {
     {"h", HARDWARE_OPT, 0},
     {"t", TEMP_OPT, 0},
   {
     {"h", HARDWARE_OPT, 0},
     {"t", TEMP_OPT, 0},
@@ -93,18 +204,24 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
     {"f", PENDING_OPT, 0},
     {"d", DISABLE_OPT, 0},
     {"a", TRACEPOINT_OPT, 0},
     {"f", PENDING_OPT, 0},
     {"d", DISABLE_OPT, 0},
     {"a", TRACEPOINT_OPT, 0},
+    {"-source" , EXPLICIT_SOURCE_OPT, 1},
+    {"-function", EXPLICIT_FUNC_OPT, 1},
+    {"-label", EXPLICIT_LABEL_OPT, 1},
+    {"-line", EXPLICIT_LINE_OPT, 1},
     { 0, 0, 0 }
   };
 
   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
      to denote the end of the option list. */
     { 0, 0, 0 }
   };
 
   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
      to denote the end of the option list. */
-  int optind = 0;
-  char *optarg;
+  int oind = 0;
+  char *oarg;
+
+  initialize_explicit_location (&explicit_loc);
 
   while (1)
     {
 
   while (1)
     {
-      int opt = mi_getopt ("mi_cmd_break_insert", argc, argv,
-                          opts, &optind, &optarg);
+      int opt = mi_getopt ("-break-insert", argc, argv,
+                          opts, &oind, &oarg);
       if (opt < 0)
        break;
       switch ((enum opt) opt)
       if (opt < 0)
        break;
       switch ((enum opt) opt)
@@ -116,13 +233,13 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
          hardware = 1;
          break;
        case CONDITION_OPT:
          hardware = 1;
          break;
        case CONDITION_OPT:
-         condition = optarg;
+         condition = oarg;
          break;
        case IGNORE_COUNT_OPT:
          break;
        case IGNORE_COUNT_OPT:
-         ignore_count = atol (optarg);
+         ignore_count = atol (oarg);
          break;
        case THREAD_OPT:
          break;
        case THREAD_OPT:
-         thread = atol (optarg);
+         thread = atol (oarg);
          break;
        case PENDING_OPT:
          pending = 1;
          break;
        case PENDING_OPT:
          pending = 1;
@@ -133,46 +250,128 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
        case TRACEPOINT_OPT:
          tracepoint = 1;
          break;
        case TRACEPOINT_OPT:
          tracepoint = 1;
          break;
+       case EXPLICIT_SOURCE_OPT:
+         is_explicit = 1;
+         explicit_loc.source_filename = oarg;
+         break;
+       case EXPLICIT_FUNC_OPT:
+         is_explicit = 1;
+         explicit_loc.function_name = oarg;
+         break;
+       case EXPLICIT_LABEL_OPT:
+         is_explicit = 1;
+         explicit_loc.label_name = oarg;
+         break;
+       case EXPLICIT_LINE_OPT:
+         is_explicit = 1;
+         explicit_loc.line_offset = linespec_parse_line_offset (oarg);
+         break;
        }
     }
 
        }
     }
 
-  if (optind >= argc)
-    error (_("mi_cmd_break_insert: Missing <location>"));
-  if (optind < argc - 1)
-    error (_("mi_cmd_break_insert: Garbage following <location>"));
-  address = argv[optind];
+  if (oind >= argc && !is_explicit)
+    error (_("-%s-insert: Missing <location>"),
+          dprintf ? "dprintf" : "break");
+  if (dprintf)
+    {
+      int format_num = is_explicit ? oind : oind + 1;
 
 
-  /* Now we have what we need, let's insert the breakpoint! */
-  if (! mi_breakpoint_observers_installed)
+      if (hardware || tracepoint)
+       error (_("-dprintf-insert: does not support -h or -a"));
+      if (format_num >= argc)
+       error (_("-dprintf-insert: Missing <format>"));
+
+      extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
+      make_cleanup (xfree, extra_string);
+      address = argv[oind];
+    }
+  else
     {
     {
-      observer_attach_breakpoint_created (breakpoint_notify);
-      observer_attach_breakpoint_modified (breakpoint_notify);
-      observer_attach_breakpoint_deleted (breakpoint_notify);
-      mi_breakpoint_observers_installed = 1;
+      if (is_explicit)
+       {
+         if (oind < argc)
+           error (_("-break-insert: Garbage following explicit location"));
+       }
+      else
+       {
+         if (oind < argc - 1)
+           error (_("-break-insert: Garbage following <location>"));
+         address = argv[oind];
+       }
     }
 
     }
 
-  back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
-  mi_can_breakpoint_notify = 1;
+  /* Now we have what we need, let's insert the breakpoint!  */
+  setup_breakpoint_reporting ();
+
+  if (tracepoint)
+    {
+      /* Note that to request a fast tracepoint, the client uses the
+        "hardware" flag, although there's nothing of hardware related to
+        fast tracepoints -- one can implement slow tracepoints with
+        hardware breakpoints, but fast tracepoints are always software.
+        "fast" is a misnomer, actually, "jump" would be more appropriate.
+        A simulator or an emulator could conceivably implement fast
+        regular non-jump based tracepoints.  */
+      type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
+      ops = &tracepoint_breakpoint_ops;
+    }
+  else if (dprintf)
+    {
+      type_wanted = bp_dprintf;
+      ops = &dprintf_breakpoint_ops;
+    }
+  else
+    {
+      type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
+      ops = &bkpt_breakpoint_ops;
+    }
 
 
-  /* Note that to request a fast tracepoint, the client uses the
-     "hardware" flag, although there's nothing of hardware related to
-     fast tracepoints -- one can implement slow tracepoints with
-     hardware breakpoints, but fast tracepoints are always software.
-     "fast" is a misnomer, actually, "jump" would be more appropriate.
-     A simulator or an emulator could conceivably implement fast
-     regular non-jump based tracepoints.  */
-  type_wanted = (tracepoint
-                ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
-                : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
-
-  create_breakpoint (get_current_arch (), address, condition, thread,
+  if (is_explicit)
+    {
+      /* Error check -- we must have one of the other
+        parameters specified.  */
+      if (explicit_loc.source_filename != NULL
+         && explicit_loc.function_name == NULL
+         && explicit_loc.label_name == NULL
+         && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
+       error (_("-%s-insert: --source option requires --function, --label,"
+                " or --line"), dprintf ? "dprintf" : "break");
+
+      location = new_explicit_location (&explicit_loc);
+    }
+  else
+    {
+      location = string_to_event_location_basic (&address, current_language);
+      if (*address)
+       error (_("Garbage '%s' at end of location"), address);
+    }
+
+  create_breakpoint (get_current_arch (), location.get (), condition, thread,
+                    extra_string,
                     0 /* condition and thread are valid.  */,
                     temp_p, type_wanted,
                     ignore_count,
                     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
                     0 /* condition and thread are valid.  */,
                     temp_p, type_wanted,
                     ignore_count,
                     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
-                    NULL, 0, enabled, 0);
+                    ops, 0, enabled, 0, 0);
   do_cleanups (back_to);
   do_cleanups (back_to);
+}
 
 
+/* Implements the -break-insert command.
+   See the MI manual for the list of possible options.  */
+
+void
+mi_cmd_break_insert (const char *command, char **argv, int argc)
+{
+  mi_cmd_break_insert_1 (0, command, argv, argc);
+}
+
+/* Implements the -dprintf-insert command.
+   See the MI manual for the list of possible options.  */
+
+void
+mi_cmd_dprintf_insert (const char *command, char **argv, int argc)
+{
+  mi_cmd_break_insert_1 (1, command, argv, argc);
 }
 
 enum wp_type
 }
 
 enum wp_type
@@ -183,11 +382,11 @@ enum wp_type
 };
 
 void
 };
 
 void
-mi_cmd_break_passcount (char *command, char **argv, int argc)
+mi_cmd_break_passcount (const char *command, char **argv, int argc)
 {
   int n;
   int p;
 {
   int n;
   int p;
-  struct breakpoint *t;
+  struct tracepoint *t;
 
   if (argc != 2)
     error (_("Usage: tracepoint-number passcount"));
 
   if (argc != 2)
     error (_("Usage: tracepoint-number passcount"));
@@ -199,11 +398,11 @@ mi_cmd_break_passcount (char *command, char **argv, int argc)
   if (t)
     {
       t->pass_count = p;
   if (t)
     {
       t->pass_count = p;
-      observer_notify_tracepoint_modified (n);
+      observer_notify_breakpoint_modified (&t->base);
     }
   else
     {
     }
   else
     {
-      error (_("Cound not find tracepoint %d"), n);
+      error (_("Could not find tracepoint %d"), n);
     }
 }
 
     }
 }
 
@@ -211,10 +410,10 @@ mi_cmd_break_passcount (char *command, char **argv, int argc)
    first argument: 
    -break-watch <expr> --> insert a regular wp.  
    -break-watch -r <expr> --> insert a read watchpoint.
    first argument: 
    -break-watch <expr> --> insert a regular wp.  
    -break-watch -r <expr> --> insert a read watchpoint.
-   -break-watch -a <expr> --> insert an access wp. */
+   -break-watch -a <expr> --> insert an access wp.  */
 
 void
 
 void
-mi_cmd_break_watch (char *command, char **argv, int argc)
+mi_cmd_break_watch (const char *command, char **argv, int argc)
 {
   char *expr = NULL;
   enum wp_type type = REG_WP;
 {
   char *expr = NULL;
   enum wp_type type = REG_WP;
@@ -222,7 +421,7 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
     {
       READ_OPT, ACCESS_OPT
     };
     {
       READ_OPT, ACCESS_OPT
     };
-  static struct mi_opt opts[] =
+  static const struct mi_opt opts[] =
   {
     {"r", READ_OPT, 0},
     {"a", ACCESS_OPT, 0},
   {
     {"r", READ_OPT, 0},
     {"a", ACCESS_OPT, 0},
@@ -230,13 +429,13 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
   };
 
   /* Parse arguments. */
   };
 
   /* Parse arguments. */
-  int optind = 0;
-  char *optarg;
+  int oind = 0;
+  char *oarg;
 
   while (1)
     {
 
   while (1)
     {
-      int opt = mi_getopt ("mi_cmd_break_watch", argc, argv,
-                          opts, &optind, &optarg);
+      int opt = mi_getopt ("-break-watch", argc, argv,
+                          opts, &oind, &oarg);
 
       if (opt < 0)
        break;
 
       if (opt < 0)
        break;
@@ -250,13 +449,13 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
          break;
        }
     }
          break;
        }
     }
-  if (optind >= argc)
-    error (_("mi_cmd_break_watch: Missing <expression>"));
-  if (optind < argc - 1)
-    error (_("mi_cmd_break_watch: Garbage following <expression>"));
-  expr = argv[optind];
+  if (oind >= argc)
+    error (_("-break-watch: Missing <expression>"));
+  if (oind < argc - 1)
+    error (_("-break-watch: Garbage following <expression>"));
+  expr = argv[oind];
 
 
-  /* Now we have what we need, let's insert the watchpoint! */
+  /* Now we have what we need, let's insert the watchpoint!  */
   switch (type)
     {
     case REG_WP:
   switch (type)
     {
     case REG_WP:
@@ -269,7 +468,7 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
       awatch_command_wrapper (expr, FROM_TTY, 0);
       break;
     default:
       awatch_command_wrapper (expr, FROM_TTY, 0);
       break;
     default:
-      error (_("mi_cmd_break_watch: Unknown watchpoint type."));
+      error (_("-break-watch: Unknown watchpoint type."));
     }
 }
 
     }
 }
 
@@ -292,27 +491,27 @@ mi_read_next_line (void)
 }
 
 void
 }
 
 void
-mi_cmd_break_commands (char *command, char **argv, int argc)
+mi_cmd_break_commands (const char *command, char **argv, int argc)
 {
 {
-  struct command_line *break_command;
+  command_line_up break_command;
   char *endptr;
   int bnum;
   struct breakpoint *b;
 
   if (argc < 1)
   char *endptr;
   int bnum;
   struct breakpoint *b;
 
   if (argc < 1)
-    error ("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]", command);
+    error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
 
   bnum = strtol (argv[0], &endptr, 0);
   if (endptr == argv[0])
 
   bnum = strtol (argv[0], &endptr, 0);
   if (endptr == argv[0])
-    error ("breakpoint number argument \"%s\" is not a number.",
+    error (_("breakpoint number argument \"%s\" is not a number."),
           argv[0]);
   else if (*endptr != '\0')
           argv[0]);
   else if (*endptr != '\0')
-    error ("junk at the end of breakpoint number argument \"%s\".",
+    error (_("junk at the end of breakpoint number argument \"%s\"."),
           argv[0]);
 
   b = get_breakpoint (bnum);
   if (b == NULL)
           argv[0]);
 
   b = get_breakpoint (bnum);
   if (b == NULL)
-    error ("breakpoint %d not found.", bnum);
+    error (_("breakpoint %d not found."), bnum);
 
   mi_command_line_array = argv;
   mi_command_line_array_ptr = 1;
 
   mi_command_line_array = argv;
   mi_command_line_array_ptr = 1;
@@ -324,6 +523,6 @@ mi_cmd_break_commands (char *command, char **argv, int argc)
   else
     break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
 
   else
     break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
 
-  breakpoint_set_commands (b, break_command);
+  breakpoint_set_commands (b, std::move (break_command));
 }
 
 }
 
This page took 0.030954 seconds and 4 git commands to generate.