198944Sobrien/* MI Command Set - breakpoint and watchpoint commands.
298944Sobrien   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
398944Sobrien   Contributed by Cygnus Solutions (a Red Hat company).
498944Sobrien
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien#include "mi-cmds.h"
2498944Sobrien#include "ui-out.h"
2598944Sobrien#include "mi-out.h"
2698944Sobrien#include "breakpoint.h"
2798944Sobrien#include "gdb_string.h"
2898944Sobrien#include "mi-getopt.h"
2998944Sobrien#include "gdb-events.h"
3098944Sobrien#include "gdb.h"
3198944Sobrien
3298944Sobrienenum
3398944Sobrien  {
3498944Sobrien    FROM_TTY = 0
3598944Sobrien  };
3698944Sobrien
3798944Sobrien/* Output a single breakpoint. */
3898944Sobrien
3998944Sobrienstatic void
4098944Sobrienbreakpoint_notify (int b)
4198944Sobrien{
4298944Sobrien  gdb_breakpoint_query (uiout, b);
4398944Sobrien}
4498944Sobrien
4598944Sobrien
4698944Sobrienstruct gdb_events breakpoint_hooks =
4798944Sobrien{
4898944Sobrien  breakpoint_notify,
4998944Sobrien  breakpoint_notify,
5098944Sobrien  breakpoint_notify,
5198944Sobrien};
5298944Sobrien
5398944Sobrien
5498944Sobrienenum bp_type
5598944Sobrien  {
5698944Sobrien    REG_BP,
5798944Sobrien    HW_BP,
5898944Sobrien    REGEXP_BP
5998944Sobrien  };
6098944Sobrien
6198944Sobrien/* Insert a breakpoint. The type of breakpoint is specified by the
6298944Sobrien   first argument: -break-insert <location> --> insert a regular
6398944Sobrien   breakpoint.  -break-insert -t <location> --> insert a temporary
6498944Sobrien   breakpoint.  -break-insert -h <location> --> insert an hardware
6598944Sobrien   breakpoint.  -break-insert -t -h <location> --> insert a temporary
6698944Sobrien   hw bp.
6798944Sobrien   -break-insert -r <regexp> --> insert a bp at functions matching
6898944Sobrien   <regexp> */
6998944Sobrien
7098944Sobrienenum mi_cmd_result
7198944Sobrienmi_cmd_break_insert (char *command, char **argv, int argc)
7298944Sobrien{
7398944Sobrien  char *address = NULL;
7498944Sobrien  enum bp_type type = REG_BP;
7598944Sobrien  int temp_p = 0;
7698944Sobrien  int thread = -1;
7798944Sobrien  int ignore_count = 0;
7898944Sobrien  char *condition = NULL;
7998944Sobrien  enum gdb_rc rc;
8098944Sobrien  struct gdb_events *old_hooks;
8198944Sobrien  enum opt
8298944Sobrien    {
8398944Sobrien      HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT,
8498944Sobrien      IGNORE_COUNT_OPT, THREAD_OPT
8598944Sobrien    };
8698944Sobrien  static struct mi_opt opts[] =
8798944Sobrien  {
8898944Sobrien    {"h", HARDWARE_OPT, 0},
8998944Sobrien    {"t", TEMP_OPT, 0},
9098944Sobrien    {"c", CONDITION_OPT, 1},
9198944Sobrien    {"i", IGNORE_COUNT_OPT, 1},
9298944Sobrien    {"p", THREAD_OPT, 1},
9398944Sobrien    0
9498944Sobrien  };
9598944Sobrien
9698944Sobrien  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
9798944Sobrien     to denote the end of the option list. */
9898944Sobrien  int optind = 0;
9998944Sobrien  char *optarg;
10098944Sobrien  while (1)
10198944Sobrien    {
10298944Sobrien      int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg);
10398944Sobrien      if (opt < 0)
10498944Sobrien	break;
10598944Sobrien      switch ((enum opt) opt)
10698944Sobrien	{
10798944Sobrien	case TEMP_OPT:
10898944Sobrien	  temp_p = 1;
10998944Sobrien	  break;
11098944Sobrien	case HARDWARE_OPT:
11198944Sobrien	  type = HW_BP;
11298944Sobrien	  break;
11398944Sobrien#if 0
11498944Sobrien	case REGEXP_OPT:
11598944Sobrien	  type = REGEXP_BP;
11698944Sobrien	  break;
11798944Sobrien#endif
11898944Sobrien	case CONDITION_OPT:
11998944Sobrien	  condition = optarg;
12098944Sobrien	  break;
12198944Sobrien	case IGNORE_COUNT_OPT:
12298944Sobrien	  ignore_count = atol (optarg);
12398944Sobrien	  break;
12498944Sobrien	case THREAD_OPT:
12598944Sobrien	  thread = atol (optarg);
12698944Sobrien	  break;
12798944Sobrien	}
12898944Sobrien    }
12998944Sobrien
13098944Sobrien  if (optind >= argc)
13198944Sobrien    error ("mi_cmd_break_insert: Missing <location>");
13298944Sobrien  if (optind < argc - 1)
13398944Sobrien    error ("mi_cmd_break_insert: Garbage following <location>");
13498944Sobrien  address = argv[optind];
13598944Sobrien
13698944Sobrien  /* Now we have what we need, let's insert the breakpoint! */
13798944Sobrien  old_hooks = set_gdb_event_hooks (&breakpoint_hooks);
13898944Sobrien  switch (type)
13998944Sobrien    {
14098944Sobrien    case REG_BP:
14198944Sobrien      rc = gdb_breakpoint (address, condition,
14298944Sobrien			   0 /*hardwareflag */ , temp_p,
14398944Sobrien			   thread, ignore_count);
14498944Sobrien      break;
14598944Sobrien    case HW_BP:
14698944Sobrien      rc = gdb_breakpoint (address, condition,
14798944Sobrien			   1 /*hardwareflag */ , temp_p,
14898944Sobrien			   thread, ignore_count);
14998944Sobrien      break;
15098944Sobrien#if 0
15198944Sobrien    case REGEXP_BP:
15298944Sobrien      if (temp_p)
15398944Sobrien	error ("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint");
15498944Sobrien      else
15598944Sobrien	rbreak_command_wrapper (address, FROM_TTY);
15698944Sobrien      return MI_CMD_DONE;
15798944Sobrien      break;
15898944Sobrien#endif
15998944Sobrien    default:
16098944Sobrien      internal_error (__FILE__, __LINE__,
16198944Sobrien		      "mi_cmd_break_insert: Bad switch.");
16298944Sobrien    }
16398944Sobrien  set_gdb_event_hooks (old_hooks);
16498944Sobrien
16598944Sobrien  if (rc == GDB_RC_FAIL)
16698944Sobrien    return MI_CMD_CAUGHT_ERROR;
16798944Sobrien  else
16898944Sobrien    return MI_CMD_DONE;
16998944Sobrien}
17098944Sobrien
17198944Sobrienenum wp_type
17298944Sobrien{
17398944Sobrien  REG_WP,
17498944Sobrien  READ_WP,
17598944Sobrien  ACCESS_WP
17698944Sobrien};
17798944Sobrien
17898944Sobrien/* Insert a watchpoint. The type of watchpoint is specified by the
17998944Sobrien   first argument:
18098944Sobrien   -break-watch <expr> --> insert a regular wp.
18198944Sobrien   -break-watch -r <expr> --> insert a read watchpoint.
18298944Sobrien   -break-watch -a <expr> --> insert an access wp. */
18398944Sobrien
18498944Sobrienenum mi_cmd_result
18598944Sobrienmi_cmd_break_watch (char *command, char **argv, int argc)
18698944Sobrien{
18798944Sobrien  char *expr = NULL;
18898944Sobrien  enum wp_type type = REG_WP;
18998944Sobrien  enum opt
19098944Sobrien    {
19198944Sobrien      READ_OPT, ACCESS_OPT
19298944Sobrien    };
19398944Sobrien  static struct mi_opt opts[] =
19498944Sobrien  {
19598944Sobrien    {"r", READ_OPT, 0},
19698944Sobrien    {"a", ACCESS_OPT, 0},
19798944Sobrien    0
19898944Sobrien  };
19998944Sobrien
20098944Sobrien  /* Parse arguments. */
20198944Sobrien  int optind = 0;
20298944Sobrien  char *optarg;
20398944Sobrien  while (1)
20498944Sobrien    {
20598944Sobrien      int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg);
20698944Sobrien      if (opt < 0)
20798944Sobrien	break;
20898944Sobrien      switch ((enum opt) opt)
20998944Sobrien	{
21098944Sobrien	case READ_OPT:
21198944Sobrien	  type = READ_WP;
21298944Sobrien	  break;
21398944Sobrien	case ACCESS_OPT:
21498944Sobrien	  type = ACCESS_WP;
21598944Sobrien	  break;
21698944Sobrien	}
21798944Sobrien    }
21898944Sobrien  if (optind >= argc)
21998944Sobrien    error ("mi_cmd_break_watch: Missing <expression>");
22098944Sobrien  if (optind < argc - 1)
22198944Sobrien    error ("mi_cmd_break_watch: Garbage following <expression>");
22298944Sobrien  expr = argv[optind];
22398944Sobrien
22498944Sobrien  /* Now we have what we need, let's insert the watchpoint! */
22598944Sobrien  switch (type)
22698944Sobrien    {
22798944Sobrien    case REG_WP:
22898944Sobrien      watch_command_wrapper (expr, FROM_TTY);
22998944Sobrien      break;
23098944Sobrien    case READ_WP:
23198944Sobrien      rwatch_command_wrapper (expr, FROM_TTY);
23298944Sobrien      break;
23398944Sobrien    case ACCESS_WP:
23498944Sobrien      awatch_command_wrapper (expr, FROM_TTY);
23598944Sobrien      break;
23698944Sobrien    default:
23798944Sobrien      error ("mi_cmd_break_watch: Unknown watchpoint type.");
23898944Sobrien    }
23998944Sobrien  return MI_CMD_DONE;
24098944Sobrien}
241