gdb: GC old versions
[dragonfly.git] / contrib / gdb-7 / gdb / mi / mi-cmd-break.c
1 /* MI Command Set - breakpoint and watchpoint commands.
2    Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4    Contributed by Cygnus Solutions (a Red Hat company).
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "arch-utils.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.h"
30 #include "exceptions.h"
31 #include "observer.h"
32
33 enum
34   {
35     FROM_TTY = 0
36   };
37
38 /* True if MI breakpoint observers have been registered.  */
39
40 static int mi_breakpoint_observers_installed;
41
42 /* Control whether breakpoint_notify may act.  */
43
44 static int mi_can_breakpoint_notify;
45
46 /* Output a single breakpoint, when allowed. */
47
48 static void
49 breakpoint_notify (int b)
50 {
51   if (mi_can_breakpoint_notify)
52     gdb_breakpoint_query (uiout, b, NULL);
53 }
54
55 enum bp_type
56   {
57     REG_BP,
58     HW_BP,
59     REGEXP_BP
60   };
61
62 /* Implements the -break-insert command.
63    See the MI manual for the list of possible options.  */
64
65 void
66 mi_cmd_break_insert (char *command, char **argv, int argc)
67 {
68   char *address = NULL;
69   enum bp_type type = REG_BP;
70   int temp_p = 0;
71   int thread = -1;
72   int ignore_count = 0;
73   char *condition = NULL;
74   int pending = 0;
75   int enabled = 1;
76
77   struct gdb_exception e;
78   struct gdb_events *old_hooks;
79   enum opt
80     {
81       HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT,
82       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT
83     };
84   static struct mi_opt opts[] =
85   {
86     {"h", HARDWARE_OPT, 0},
87     {"t", TEMP_OPT, 0},
88     {"c", CONDITION_OPT, 1},
89     {"i", IGNORE_COUNT_OPT, 1},
90     {"p", THREAD_OPT, 1},
91     {"f", PENDING_OPT, 0},
92     {"d", DISABLE_OPT, 0},
93     { 0, 0, 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         case PENDING_OPT:
128           pending = 1;
129           break;
130         case DISABLE_OPT:
131           enabled = 0;
132         }
133     }
134
135   if (optind >= argc)
136     error (_("mi_cmd_break_insert: Missing <location>"));
137   if (optind < argc - 1)
138     error (_("mi_cmd_break_insert: Garbage following <location>"));
139   address = argv[optind];
140
141   /* Now we have what we need, let's insert the breakpoint! */
142   if (! mi_breakpoint_observers_installed)
143     {
144       observer_attach_breakpoint_created (breakpoint_notify);
145       observer_attach_breakpoint_modified (breakpoint_notify);
146       observer_attach_breakpoint_deleted (breakpoint_notify);
147       mi_breakpoint_observers_installed = 1;
148     }
149
150   mi_can_breakpoint_notify = 1;
151   /* Make sure we restore hooks even if exception is thrown.  */
152   TRY_CATCH (e, RETURN_MASK_ALL)
153     {
154       switch (type)
155         {
156         case REG_BP:
157           set_breakpoint (get_current_arch (), address, condition,
158                           0 /*hardwareflag */ , temp_p,
159                           thread, ignore_count,
160                           pending, enabled);
161           break;
162         case HW_BP:
163           set_breakpoint (get_current_arch (), address, condition,
164                           1 /*hardwareflag */ , temp_p,
165                           thread, ignore_count,
166                           pending, enabled);
167           break;
168 #if 0
169         case REGEXP_BP:
170           if (temp_p)
171             error (_("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint"));
172           else
173             rbreak_command_wrapper (address, FROM_TTY);
174           break;
175 #endif
176         default:
177           internal_error (__FILE__, __LINE__,
178                           _("mi_cmd_break_insert: Bad switch."));
179         }
180     }
181   mi_can_breakpoint_notify = 0;
182   if (e.reason < 0)
183     throw_exception (e);
184 }
185
186 enum wp_type
187 {
188   REG_WP,
189   READ_WP,
190   ACCESS_WP
191 };
192
193 /* Insert a watchpoint. The type of watchpoint is specified by the
194    first argument: 
195    -break-watch <expr> --> insert a regular wp.  
196    -break-watch -r <expr> --> insert a read watchpoint.
197    -break-watch -a <expr> --> insert an access wp. */
198
199 void
200 mi_cmd_break_watch (char *command, char **argv, int argc)
201 {
202   char *expr = NULL;
203   enum wp_type type = REG_WP;
204   enum opt
205     {
206       READ_OPT, ACCESS_OPT
207     };
208   static struct mi_opt opts[] =
209   {
210     {"r", READ_OPT, 0},
211     {"a", ACCESS_OPT, 0},
212     { 0, 0, 0 }
213   };
214
215   /* Parse arguments. */
216   int optind = 0;
217   char *optarg;
218   while (1)
219     {
220       int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg);
221       if (opt < 0)
222         break;
223       switch ((enum opt) opt)
224         {
225         case READ_OPT:
226           type = READ_WP;
227           break;
228         case ACCESS_OPT:
229           type = ACCESS_WP;
230           break;
231         }
232     }
233   if (optind >= argc)
234     error (_("mi_cmd_break_watch: Missing <expression>"));
235   if (optind < argc - 1)
236     error (_("mi_cmd_break_watch: Garbage following <expression>"));
237   expr = argv[optind];
238
239   /* Now we have what we need, let's insert the watchpoint! */
240   switch (type)
241     {
242     case REG_WP:
243       watch_command_wrapper (expr, FROM_TTY);
244       break;
245     case READ_WP:
246       rwatch_command_wrapper (expr, FROM_TTY);
247       break;
248     case ACCESS_WP:
249       awatch_command_wrapper (expr, FROM_TTY);
250       break;
251     default:
252       error (_("mi_cmd_break_watch: Unknown watchpoint type."));
253     }
254 }
255
256 /* The mi_read_next_line consults these variable to return successive
257    command lines.  While it would be clearer to use a closure pointer,
258    it is not expected that any future code will use read_command_lines_1,
259    therefore no point of overengineering.  */
260
261 static char **mi_command_line_array;
262 static int mi_command_line_array_cnt;
263 static int mi_command_line_array_ptr;
264
265 static char *
266 mi_read_next_line ()
267 {
268   if (mi_command_line_array_ptr == mi_command_line_array_cnt)
269     return NULL;
270   else
271     return mi_command_line_array[mi_command_line_array_ptr++];
272 }
273
274 void
275 mi_cmd_break_commands (char *command, char **argv, int argc)
276 {
277   struct command_line *break_command;
278   char *endptr;
279   int bnum;
280   struct breakpoint *b;
281
282   if (argc < 1)
283     error ("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]", command);
284
285   bnum = strtol (argv[0], &endptr, 0);
286   if (endptr == argv[0])
287     error ("breakpoint number argument \"%s\" is not a number.",
288            argv[0]);
289   else if (*endptr != '\0')
290     error ("junk at the end of breakpoint number argument \"%s\".",
291            argv[0]);
292
293   b = get_breakpoint (bnum);
294   if (b == NULL)
295     error ("breakpoint %d not found.", bnum);
296
297   mi_command_line_array = argv;
298   mi_command_line_array_ptr = 1;
299   mi_command_line_array_cnt = argc;
300
301   break_command = read_command_lines_1 (mi_read_next_line, 0);
302   breakpoint_set_commands (b, break_command);
303 }
304