1/* MI Command Set - breakpoint and watchpoint commands.
2   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
3   Contributed by Cygnus Solutions (a Red Hat company).
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.  */
21
22#include "defs.h"
23#include "mi-cmds.h"
24#include "ui-out.h"
25#include "mi-out.h"
26#include "breakpoint.h"
27#include "gdb_string.h"
28#include "mi-getopt.h"
29#include "gdb-events.h"
30#include "gdb.h"
31
32enum
33  {
34    FROM_TTY = 0
35  };
36
37/* Output a single breakpoint. */
38
39static void
40breakpoint_notify (int b)
41{
42  gdb_breakpoint_query (uiout, b);
43}
44
45
46struct gdb_events breakpoint_hooks =
47{
48  breakpoint_notify,
49  breakpoint_notify,
50  breakpoint_notify,
51};
52
53
54enum bp_type
55  {
56    REG_BP,
57    HW_BP,
58    REGEXP_BP
59  };
60
61/* Insert a breakpoint. The type of breakpoint is specified by the
62   first argument: -break-insert <location> --> insert a regular
63   breakpoint.  -break-insert -t <location> --> insert a temporary
64   breakpoint.  -break-insert -h <location> --> insert an hardware
65   breakpoint.  -break-insert -t -h <location> --> insert a temporary
66   hw bp.
67   -break-insert -r <regexp> --> insert a bp at functions matching
68   <regexp> */
69
70enum mi_cmd_result
71mi_cmd_break_insert (char *command, char **argv, int argc)
72{
73  char *address = NULL;
74  enum bp_type type = REG_BP;
75  int temp_p = 0;
76  int thread = -1;
77  int ignore_count = 0;
78  char *condition = NULL;
79  enum gdb_rc rc;
80  struct gdb_events *old_hooks;
81  enum opt
82    {
83      HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT,
84      IGNORE_COUNT_OPT, THREAD_OPT
85    };
86  static struct mi_opt opts[] =
87  {
88    {"h", HARDWARE_OPT, 0},
89    {"t", TEMP_OPT, 0},
90    {"c", CONDITION_OPT, 1},
91    {"i", IGNORE_COUNT_OPT, 1},
92    {"p", THREAD_OPT, 1},
93    0
94  };
95
96  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
97     to denote the end of the option list. */
98  int optind = 0;
99  char *optarg;
100  while (1)
101    {
102      int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg);
103      if (opt < 0)
104	break;
105      switch ((enum opt) opt)
106	{
107	case TEMP_OPT:
108	  temp_p = 1;
109	  break;
110	case HARDWARE_OPT:
111	  type = HW_BP;
112	  break;
113#if 0
114	case REGEXP_OPT:
115	  type = REGEXP_BP;
116	  break;
117#endif
118	case CONDITION_OPT:
119	  condition = optarg;
120	  break;
121	case IGNORE_COUNT_OPT:
122	  ignore_count = atol (optarg);
123	  break;
124	case THREAD_OPT:
125	  thread = atol (optarg);
126	  break;
127	}
128    }
129
130  if (optind >= argc)
131    error ("mi_cmd_break_insert: Missing <location>");
132  if (optind < argc - 1)
133    error ("mi_cmd_break_insert: Garbage following <location>");
134  address = argv[optind];
135
136  /* Now we have what we need, let's insert the breakpoint! */
137  old_hooks = deprecated_set_gdb_event_hooks (&breakpoint_hooks);
138  switch (type)
139    {
140    case REG_BP:
141      rc = gdb_breakpoint (address, condition,
142			   0 /*hardwareflag */ , temp_p,
143			   thread, ignore_count);
144      break;
145    case HW_BP:
146      rc = gdb_breakpoint (address, condition,
147			   1 /*hardwareflag */ , temp_p,
148			   thread, ignore_count);
149      break;
150#if 0
151    case REGEXP_BP:
152      if (temp_p)
153	error ("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint");
154      else
155	rbreak_command_wrapper (address, FROM_TTY);
156      return MI_CMD_DONE;
157      break;
158#endif
159    default:
160      internal_error (__FILE__, __LINE__,
161		      "mi_cmd_break_insert: Bad switch.");
162    }
163  deprecated_set_gdb_event_hooks (old_hooks);
164
165  if (rc == GDB_RC_FAIL)
166    return MI_CMD_CAUGHT_ERROR;
167  else
168    return MI_CMD_DONE;
169}
170
171enum wp_type
172{
173  REG_WP,
174  READ_WP,
175  ACCESS_WP
176};
177
178/* Insert a watchpoint. The type of watchpoint is specified by the
179   first argument:
180   -break-watch <expr> --> insert a regular wp.
181   -break-watch -r <expr> --> insert a read watchpoint.
182   -break-watch -a <expr> --> insert an access wp. */
183
184enum mi_cmd_result
185mi_cmd_break_watch (char *command, char **argv, int argc)
186{
187  char *expr = NULL;
188  enum wp_type type = REG_WP;
189  enum opt
190    {
191      READ_OPT, ACCESS_OPT
192    };
193  static struct mi_opt opts[] =
194  {
195    {"r", READ_OPT, 0},
196    {"a", ACCESS_OPT, 0},
197    0
198  };
199
200  /* Parse arguments. */
201  int optind = 0;
202  char *optarg;
203  while (1)
204    {
205      int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg);
206      if (opt < 0)
207	break;
208      switch ((enum opt) opt)
209	{
210	case READ_OPT:
211	  type = READ_WP;
212	  break;
213	case ACCESS_OPT:
214	  type = ACCESS_WP;
215	  break;
216	}
217    }
218  if (optind >= argc)
219    error ("mi_cmd_break_watch: Missing <expression>");
220  if (optind < argc - 1)
221    error ("mi_cmd_break_watch: Garbage following <expression>");
222  expr = argv[optind];
223
224  /* Now we have what we need, let's insert the watchpoint! */
225  switch (type)
226    {
227    case REG_WP:
228      watch_command_wrapper (expr, FROM_TTY);
229      break;
230    case READ_WP:
231      rwatch_command_wrapper (expr, FROM_TTY);
232      break;
233    case ACCESS_WP:
234      awatch_command_wrapper (expr, FROM_TTY);
235      break;
236    default:
237      error ("mi_cmd_break_watch: Unknown watchpoint type.");
238    }
239  return MI_CMD_DONE;
240}
241