Use counted_command_line everywhere
[external/binutils.git] / gdb / mi / mi-cmd-break.c
1 /* MI Command Set - breakpoint and watchpoint commands.
2    Copyright (C) 2000-2018 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "arch-utils.h"
22 #include "mi-cmds.h"
23 #include "ui-out.h"
24 #include "mi-out.h"
25 #include "breakpoint.h"
26 #include "mi-getopt.h"
27 #include "observable.h"
28 #include "mi-main.h"
29 #include "mi-cmd-break.h"
30 #include "language.h"
31 #include "location.h"
32 #include "linespec.h"
33 #include "gdb_obstack.h"
34 #include <ctype.h>
35
36 enum
37   {
38     FROM_TTY = 0
39   };
40
41 /* True if MI breakpoint observers have been registered.  */
42
43 static int mi_breakpoint_observers_installed;
44
45 /* Control whether breakpoint_notify may act.  */
46
47 static int mi_can_breakpoint_notify;
48
49 /* Output a single breakpoint, when allowed.  */
50
51 static void
52 breakpoint_notify (struct breakpoint *b)
53 {
54   if (mi_can_breakpoint_notify)
55     {
56       TRY
57         {
58           print_breakpoint (b);
59         }
60       CATCH (ex, RETURN_MASK_ALL)
61         {
62           exception_print (gdb_stderr, ex);
63         }
64       END_CATCH
65     }
66 }
67
68 enum bp_type
69   {
70     REG_BP,
71     HW_BP,
72     REGEXP_BP
73   };
74
75 /* Arrange for all new breakpoints and catchpoints to be reported to
76    CURRENT_UIOUT until the destructor of the returned scoped_restore
77    is run.
78
79    Note that MI output will be probably invalid if more than one
80    breakpoint is created inside one MI command.  */
81
82 scoped_restore_tmpl<int>
83 setup_breakpoint_reporting (void)
84 {
85   if (! mi_breakpoint_observers_installed)
86     {
87       gdb::observers::breakpoint_created.attach (breakpoint_notify);
88       mi_breakpoint_observers_installed = 1;
89     }
90
91   return make_scoped_restore (&mi_can_breakpoint_notify, 1);
92 }
93
94
95 /* Convert arguments in ARGV to the string in "format",argv,argv...
96    and return it.  */
97
98 static std::string
99 mi_argv_to_format (char **argv, int argc)
100 {
101   int i;
102   std::string result;
103
104   /* Convert ARGV[OIND + 1] to format string and save to FORMAT.  */
105   result += '\"';
106   for (i = 0; i < strlen (argv[0]); i++)
107     {
108       switch (argv[0][i])
109         {
110         case '\\':
111           result += "\\\\";
112           break;
113         case '\a':
114           result += "\\a";
115           break;
116         case '\b':
117           result += "\\b";
118           break;
119         case '\f':
120           result += "\\f";
121           break;
122         case '\n':
123           result += "\\n";
124           break;
125         case '\r':
126           result += "\\r";
127           break;
128         case '\t':
129           result += "\\t";
130           break;
131         case '\v':
132           result += "\\v";
133           break;
134         case '"':
135           result += "\\\"";
136           break;
137         default:
138           if (isprint (argv[0][i]))
139             result += argv[0][i];
140           else
141             {
142               char tmp[5];
143
144               xsnprintf (tmp, sizeof (tmp), "\\%o",
145                          (unsigned char) argv[0][i]);
146               result += tmp;
147             }
148           break;
149         }
150     }
151   result += '\"';
152
153   /* Apply other argv to FORMAT.  */
154   for (i = 1; i < argc; i++)
155     {
156       result += ',';
157       result += argv[i];
158     }
159
160   return result;
161 }
162
163 /* Insert breakpoint.
164    If dprintf is true, it will insert dprintf.
165    If not, it will insert other type breakpoint.  */
166
167 static void
168 mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
169 {
170   const char *address = NULL;
171   int hardware = 0;
172   int temp_p = 0;
173   int thread = -1;
174   int ignore_count = 0;
175   char *condition = NULL;
176   int pending = 0;
177   int enabled = 1;
178   int tracepoint = 0;
179   enum bptype type_wanted;
180   event_location_up location;
181   struct breakpoint_ops *ops;
182   int is_explicit = 0;
183   struct explicit_location explicit_loc;
184   std::string extra_string;
185
186   enum opt
187     {
188       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
189       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
190       TRACEPOINT_OPT,
191       EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
192       EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
193     };
194   static const struct mi_opt opts[] =
195   {
196     {"h", HARDWARE_OPT, 0},
197     {"t", TEMP_OPT, 0},
198     {"c", CONDITION_OPT, 1},
199     {"i", IGNORE_COUNT_OPT, 1},
200     {"p", THREAD_OPT, 1},
201     {"f", PENDING_OPT, 0},
202     {"d", DISABLE_OPT, 0},
203     {"a", TRACEPOINT_OPT, 0},
204     {"-source" , EXPLICIT_SOURCE_OPT, 1},
205     {"-function", EXPLICIT_FUNC_OPT, 1},
206     {"-label", EXPLICIT_LABEL_OPT, 1},
207     {"-line", EXPLICIT_LINE_OPT, 1},
208     { 0, 0, 0 }
209   };
210
211   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
212      to denote the end of the option list. */
213   int oind = 0;
214   char *oarg;
215
216   initialize_explicit_location (&explicit_loc);
217
218   while (1)
219     {
220       int opt = mi_getopt ("-break-insert", argc, argv,
221                            opts, &oind, &oarg);
222       if (opt < 0)
223         break;
224       switch ((enum opt) opt)
225         {
226         case TEMP_OPT:
227           temp_p = 1;
228           break;
229         case HARDWARE_OPT:
230           hardware = 1;
231           break;
232         case CONDITION_OPT:
233           condition = oarg;
234           break;
235         case IGNORE_COUNT_OPT:
236           ignore_count = atol (oarg);
237           break;
238         case THREAD_OPT:
239           thread = atol (oarg);
240           break;
241         case PENDING_OPT:
242           pending = 1;
243           break;
244         case DISABLE_OPT:
245           enabled = 0;
246           break;
247         case TRACEPOINT_OPT:
248           tracepoint = 1;
249           break;
250         case EXPLICIT_SOURCE_OPT:
251           is_explicit = 1;
252           explicit_loc.source_filename = oarg;
253           break;
254         case EXPLICIT_FUNC_OPT:
255           is_explicit = 1;
256           explicit_loc.function_name = oarg;
257           break;
258         case EXPLICIT_LABEL_OPT:
259           is_explicit = 1;
260           explicit_loc.label_name = oarg;
261           break;
262         case EXPLICIT_LINE_OPT:
263           is_explicit = 1;
264           explicit_loc.line_offset = linespec_parse_line_offset (oarg);
265           break;
266         }
267     }
268
269   if (oind >= argc && !is_explicit)
270     error (_("-%s-insert: Missing <location>"),
271            dprintf ? "dprintf" : "break");
272   if (dprintf)
273     {
274       int format_num = is_explicit ? oind : oind + 1;
275
276       if (hardware || tracepoint)
277         error (_("-dprintf-insert: does not support -h or -a"));
278       if (format_num >= argc)
279         error (_("-dprintf-insert: Missing <format>"));
280
281       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
282       address = argv[oind];
283     }
284   else
285     {
286       if (is_explicit)
287         {
288           if (oind < argc)
289             error (_("-break-insert: Garbage following explicit location"));
290         }
291       else
292         {
293           if (oind < argc - 1)
294             error (_("-break-insert: Garbage following <location>"));
295           address = argv[oind];
296         }
297     }
298
299   /* Now we have what we need, let's insert the breakpoint!  */
300   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
301
302   if (tracepoint)
303     {
304       /* Note that to request a fast tracepoint, the client uses the
305          "hardware" flag, although there's nothing of hardware related to
306          fast tracepoints -- one can implement slow tracepoints with
307          hardware breakpoints, but fast tracepoints are always software.
308          "fast" is a misnomer, actually, "jump" would be more appropriate.
309          A simulator or an emulator could conceivably implement fast
310          regular non-jump based tracepoints.  */
311       type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
312       ops = &tracepoint_breakpoint_ops;
313     }
314   else if (dprintf)
315     {
316       type_wanted = bp_dprintf;
317       ops = &dprintf_breakpoint_ops;
318     }
319   else
320     {
321       type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
322       ops = &bkpt_breakpoint_ops;
323     }
324
325   if (is_explicit)
326     {
327       /* Error check -- we must have one of the other
328          parameters specified.  */
329       if (explicit_loc.source_filename != NULL
330           && explicit_loc.function_name == NULL
331           && explicit_loc.label_name == NULL
332           && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
333         error (_("-%s-insert: --source option requires --function, --label,"
334                  " or --line"), dprintf ? "dprintf" : "break");
335
336       location = new_explicit_location (&explicit_loc);
337     }
338   else
339     {
340       location = string_to_event_location_basic (&address, current_language,
341                                                  symbol_name_match_type::WILD);
342       if (*address)
343         error (_("Garbage '%s' at end of location"), address);
344     }
345
346   create_breakpoint (get_current_arch (), location.get (), condition, thread,
347                      extra_string.c_str (),
348                      0 /* condition and thread are valid.  */,
349                      temp_p, type_wanted,
350                      ignore_count,
351                      pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
352                      ops, 0, enabled, 0, 0);
353 }
354
355 /* Implements the -break-insert command.
356    See the MI manual for the list of possible options.  */
357
358 void
359 mi_cmd_break_insert (const char *command, char **argv, int argc)
360 {
361   mi_cmd_break_insert_1 (0, command, argv, argc);
362 }
363
364 /* Implements the -dprintf-insert command.
365    See the MI manual for the list of possible options.  */
366
367 void
368 mi_cmd_dprintf_insert (const char *command, char **argv, int argc)
369 {
370   mi_cmd_break_insert_1 (1, command, argv, argc);
371 }
372
373 enum wp_type
374 {
375   REG_WP,
376   READ_WP,
377   ACCESS_WP
378 };
379
380 void
381 mi_cmd_break_passcount (const char *command, char **argv, int argc)
382 {
383   int n;
384   int p;
385   struct tracepoint *t;
386
387   if (argc != 2)
388     error (_("Usage: tracepoint-number passcount"));
389
390   n = atoi (argv[0]);
391   p = atoi (argv[1]);
392   t = get_tracepoint (n);
393
394   if (t)
395     {
396       t->pass_count = p;
397       gdb::observers::breakpoint_modified.notify (t);
398     }
399   else
400     {
401       error (_("Could not find tracepoint %d"), n);
402     }
403 }
404
405 /* Insert a watchpoint. The type of watchpoint is specified by the
406    first argument: 
407    -break-watch <expr> --> insert a regular wp.  
408    -break-watch -r <expr> --> insert a read watchpoint.
409    -break-watch -a <expr> --> insert an access wp.  */
410
411 void
412 mi_cmd_break_watch (const char *command, char **argv, int argc)
413 {
414   char *expr = NULL;
415   enum wp_type type = REG_WP;
416   enum opt
417     {
418       READ_OPT, ACCESS_OPT
419     };
420   static const struct mi_opt opts[] =
421   {
422     {"r", READ_OPT, 0},
423     {"a", ACCESS_OPT, 0},
424     { 0, 0, 0 }
425   };
426
427   /* Parse arguments. */
428   int oind = 0;
429   char *oarg;
430
431   while (1)
432     {
433       int opt = mi_getopt ("-break-watch", argc, argv,
434                            opts, &oind, &oarg);
435
436       if (opt < 0)
437         break;
438       switch ((enum opt) opt)
439         {
440         case READ_OPT:
441           type = READ_WP;
442           break;
443         case ACCESS_OPT:
444           type = ACCESS_WP;
445           break;
446         }
447     }
448   if (oind >= argc)
449     error (_("-break-watch: Missing <expression>"));
450   if (oind < argc - 1)
451     error (_("-break-watch: Garbage following <expression>"));
452   expr = argv[oind];
453
454   /* Now we have what we need, let's insert the watchpoint!  */
455   switch (type)
456     {
457     case REG_WP:
458       watch_command_wrapper (expr, FROM_TTY, 0);
459       break;
460     case READ_WP:
461       rwatch_command_wrapper (expr, FROM_TTY, 0);
462       break;
463     case ACCESS_WP:
464       awatch_command_wrapper (expr, FROM_TTY, 0);
465       break;
466     default:
467       error (_("-break-watch: Unknown watchpoint type."));
468     }
469 }
470
471 /* The mi_read_next_line consults these variable to return successive
472    command lines.  While it would be clearer to use a closure pointer,
473    it is not expected that any future code will use read_command_lines_1,
474    therefore no point of overengineering.  */
475
476 static char **mi_command_line_array;
477 static int mi_command_line_array_cnt;
478 static int mi_command_line_array_ptr;
479
480 static char *
481 mi_read_next_line (void)
482 {
483   if (mi_command_line_array_ptr == mi_command_line_array_cnt)
484     return NULL;
485   else
486     return mi_command_line_array[mi_command_line_array_ptr++];
487 }
488
489 void
490 mi_cmd_break_commands (const char *command, char **argv, int argc)
491 {
492   counted_command_line break_command;
493   char *endptr;
494   int bnum;
495   struct breakpoint *b;
496
497   if (argc < 1)
498     error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
499
500   bnum = strtol (argv[0], &endptr, 0);
501   if (endptr == argv[0])
502     error (_("breakpoint number argument \"%s\" is not a number."),
503            argv[0]);
504   else if (*endptr != '\0')
505     error (_("junk at the end of breakpoint number argument \"%s\"."),
506            argv[0]);
507
508   b = get_breakpoint (bnum);
509   if (b == NULL)
510     error (_("breakpoint %d not found."), bnum);
511
512   mi_command_line_array = argv;
513   mi_command_line_array_ptr = 1;
514   mi_command_line_array_cnt = argc;
515
516   if (is_tracepoint (b))
517     break_command = read_command_lines_1 (mi_read_next_line, 1,
518                                           check_tracepoint_command, b);
519   else
520     break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
521
522   breakpoint_set_commands (b, std::move (break_command));
523 }
524