1 /* Scheme interface to breakpoints.
2 
3    Copyright (C) 2008-2020 Free Software Foundation, Inc.
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 /* See README file in this directory for implementation notes, coding
21    conventions, et.al.  */
22 
23 #include "defs.h"
24 #include "value.h"
25 #include "breakpoint.h"
26 #include "gdbcmd.h"
27 #include "gdbthread.h"
28 #include "observable.h"
29 #include "cli/cli-script.h"
30 #include "ada-lang.h"
31 #include "arch-utils.h"
32 #include "language.h"
33 #include "guile-internal.h"
34 #include "location.h"
35 
36 /* The <gdb:breakpoint> smob.
37    N.B.: The name of this struct is known to breakpoint.h.
38 
39    Note: Breakpoints are added to gdb using a two step process:
40    1) Call make-breakpoint to create a <gdb:breakpoint> object.
41    2) Call register-breakpoint! to add the breakpoint to gdb.
42    It is done this way so that the constructor, make-breakpoint, doesn't have
43    any side-effects.  This means that the smob needs to store everything
44    that was passed to make-breakpoint.  */
45 
46 typedef struct gdbscm_breakpoint_object
47 {
48   /* This always appears first.  */
49   gdb_smob base;
50 
51   /* Non-zero if this breakpoint was created with make-breakpoint.  */
52   int is_scheme_bkpt;
53 
54   /* For breakpoints created with make-breakpoint, these are the parameters
55      that were passed to make-breakpoint.  These values are not used except
56      to register the breakpoint with GDB.  */
57   struct
58   {
59     /* The string representation of the breakpoint.
60        Space for this lives in GC space.  */
61     char *location;
62 
63     /* The kind of breakpoint.
64        At the moment this can only be one of bp_breakpoint, bp_watchpoint.  */
65     enum bptype type;
66 
67     /* If a watchpoint, the kind of watchpoint.  */
68     enum target_hw_bp_type access_type;
69 
70     /* Non-zero if the breakpoint is an "internal" breakpoint.  */
71     int is_internal;
72   } spec;
73 
74   /* The breakpoint number according to gdb.
75      For breakpoints created from Scheme, this has the value -1 until the
76      breakpoint is registered with gdb.
77      This is recorded here because BP will be NULL when deleted.  */
78   int number;
79 
80   /* The gdb breakpoint object, or NULL if the breakpoint has not been
81      registered yet, or has been deleted.  */
82   struct breakpoint *bp;
83 
84   /* Backlink to our containing <gdb:breakpoint> smob.
85      This is needed when we are deleted, we need to unprotect the object
86      from GC.  */
87   SCM containing_scm;
88 
89   /* A stop condition or #f.  */
90   SCM stop;
91 } breakpoint_smob;
92 
93 static const char breakpoint_smob_name[] = "gdb:breakpoint";
94 
95 /* The tag Guile knows the breakpoint smob by.  */
96 static scm_t_bits breakpoint_smob_tag;
97 
98 /* Variables used to pass information between the breakpoint_smob
99    constructor and the breakpoint-created hook function.  */
100 static SCM pending_breakpoint_scm = SCM_BOOL_F;
101 
102 /* Keywords used by create-breakpoint!.  */
103 static SCM type_keyword;
104 static SCM wp_class_keyword;
105 static SCM internal_keyword;
106 
107 /* Administrivia for breakpoint smobs.  */
108 
109 /* The smob "free" function for <gdb:breakpoint>.  */
110 
111 static size_t
bpscm_free_breakpoint_smob(SCM self)112 bpscm_free_breakpoint_smob (SCM self)
113 {
114   breakpoint_smob *bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (self);
115 
116   if (bp_smob->bp)
117     bp_smob->bp->scm_bp_object = NULL;
118 
119   /* Not necessary, done to catch bugs.  */
120   bp_smob->bp = NULL;
121   bp_smob->containing_scm = SCM_UNDEFINED;
122   bp_smob->stop = SCM_UNDEFINED;
123 
124   return 0;
125 }
126 
127 /* Return the name of TYPE.
128    This doesn't handle all types, just the ones we export.  */
129 
130 static const char *
bpscm_type_to_string(enum bptype type)131 bpscm_type_to_string (enum bptype type)
132 {
133   switch (type)
134     {
135     case bp_none: return "BP_NONE";
136     case bp_breakpoint: return "BP_BREAKPOINT";
137     case bp_watchpoint: return "BP_WATCHPOINT";
138     case bp_hardware_watchpoint: return "BP_HARDWARE_WATCHPOINT";
139     case bp_read_watchpoint: return "BP_READ_WATCHPOINT";
140     case bp_access_watchpoint: return "BP_ACCESS_WATCHPOINT";
141     default: return "internal/other";
142     }
143 }
144 
145 /* Return the name of ENABLE_STATE.  */
146 
147 static const char *
bpscm_enable_state_to_string(enum enable_state enable_state)148 bpscm_enable_state_to_string (enum enable_state enable_state)
149 {
150   switch (enable_state)
151     {
152     case bp_disabled: return "disabled";
153     case bp_enabled: return "enabled";
154     case bp_call_disabled: return "call_disabled";
155     default: return "unknown";
156     }
157 }
158 
159 /* The smob "print" function for <gdb:breakpoint>.  */
160 
161 static int
bpscm_print_breakpoint_smob(SCM self,SCM port,scm_print_state * pstate)162 bpscm_print_breakpoint_smob (SCM self, SCM port, scm_print_state *pstate)
163 {
164   breakpoint_smob *bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (self);
165   struct breakpoint *b = bp_smob->bp;
166 
167   gdbscm_printf (port, "#<%s", breakpoint_smob_name);
168 
169   /* Only print what we export to the user.
170      The rest are possibly internal implementation details.  */
171 
172   gdbscm_printf (port, " #%d", bp_smob->number);
173 
174   /* Careful, the breakpoint may be invalid.  */
175   if (b != NULL)
176     {
177       const char *str;
178 
179       gdbscm_printf (port, " %s %s %s",
180 		     bpscm_type_to_string (b->type),
181 		     bpscm_enable_state_to_string (b->enable_state),
182 		     b->silent ? "silent" : "noisy");
183 
184       gdbscm_printf (port, " hit:%d", b->hit_count);
185       gdbscm_printf (port, " ignore:%d", b->ignore_count);
186 
187       str = event_location_to_string (b->location.get ());
188       if (str != NULL)
189 	gdbscm_printf (port, " @%s", str);
190     }
191 
192   scm_puts (">", port);
193 
194   scm_remember_upto_here_1 (self);
195 
196   /* Non-zero means success.  */
197   return 1;
198 }
199 
200 /* Low level routine to create a <gdb:breakpoint> object.  */
201 
202 static SCM
bpscm_make_breakpoint_smob(void)203 bpscm_make_breakpoint_smob (void)
204 {
205   breakpoint_smob *bp_smob = (breakpoint_smob *)
206     scm_gc_malloc (sizeof (breakpoint_smob), breakpoint_smob_name);
207   SCM bp_scm;
208 
209   memset (bp_smob, 0, sizeof (*bp_smob));
210   bp_smob->number = -1;
211   bp_smob->stop = SCM_BOOL_F;
212   bp_scm = scm_new_smob (breakpoint_smob_tag, (scm_t_bits) bp_smob);
213   bp_smob->containing_scm = bp_scm;
214   gdbscm_init_gsmob (&bp_smob->base);
215 
216   return bp_scm;
217 }
218 
219 /* Return non-zero if we want a Scheme wrapper for breakpoint B.
220    If FROM_SCHEME is non-zero,this is called for a breakpoint created
221    by the user from Scheme.  Otherwise it is zero.  */
222 
223 static int
bpscm_want_scm_wrapper_p(struct breakpoint * bp,int from_scheme)224 bpscm_want_scm_wrapper_p (struct breakpoint *bp, int from_scheme)
225 {
226   /* Don't create <gdb:breakpoint> objects for internal GDB breakpoints.  */
227   if (bp->number < 0 && !from_scheme)
228     return 0;
229 
230   /* The others are not supported.  */
231   if (bp->type != bp_breakpoint
232       && bp->type != bp_watchpoint
233       && bp->type != bp_hardware_watchpoint
234       && bp->type != bp_read_watchpoint
235       && bp->type != bp_access_watchpoint)
236     return 0;
237 
238   return 1;
239 }
240 
241 /* Install the Scheme side of a breakpoint, CONTAINING_SCM, in
242    the gdb side BP.  */
243 
244 static void
bpscm_attach_scm_to_breakpoint(struct breakpoint * bp,SCM containing_scm)245 bpscm_attach_scm_to_breakpoint (struct breakpoint *bp, SCM containing_scm)
246 {
247   breakpoint_smob *bp_smob;
248 
249   bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (containing_scm);
250   bp_smob->number = bp->number;
251   bp_smob->bp = bp;
252   bp_smob->containing_scm = containing_scm;
253   bp_smob->bp->scm_bp_object = bp_smob;
254 
255   /* The owner of this breakpoint is not in GC-controlled memory, so we need
256      to protect it from GC until the breakpoint is deleted.  */
257   scm_gc_protect_object (containing_scm);
258 }
259 
260 /* Return non-zero if SCM is a breakpoint smob.  */
261 
262 static int
bpscm_is_breakpoint(SCM scm)263 bpscm_is_breakpoint (SCM scm)
264 {
265   return SCM_SMOB_PREDICATE (breakpoint_smob_tag, scm);
266 }
267 
268 /* (breakpoint? scm) -> boolean */
269 
270 static SCM
gdbscm_breakpoint_p(SCM scm)271 gdbscm_breakpoint_p (SCM scm)
272 {
273   return scm_from_bool (bpscm_is_breakpoint (scm));
274 }
275 
276 /* Returns the <gdb:breakpoint> object in SELF.
277    Throws an exception if SELF is not a <gdb:breakpoint> object.  */
278 
279 static SCM
bpscm_get_breakpoint_arg_unsafe(SCM self,int arg_pos,const char * func_name)280 bpscm_get_breakpoint_arg_unsafe (SCM self, int arg_pos, const char *func_name)
281 {
282   SCM_ASSERT_TYPE (bpscm_is_breakpoint (self), self, arg_pos, func_name,
283 		   breakpoint_smob_name);
284 
285   return self;
286 }
287 
288 /* Returns a pointer to the breakpoint smob of SELF.
289    Throws an exception if SELF is not a <gdb:breakpoint> object.  */
290 
291 static breakpoint_smob *
bpscm_get_breakpoint_smob_arg_unsafe(SCM self,int arg_pos,const char * func_name)292 bpscm_get_breakpoint_smob_arg_unsafe (SCM self, int arg_pos,
293 				      const char *func_name)
294 {
295   SCM bp_scm = bpscm_get_breakpoint_arg_unsafe (self, arg_pos, func_name);
296   breakpoint_smob *bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (bp_scm);
297 
298   return bp_smob;
299 }
300 
301 /* Return non-zero if breakpoint BP_SMOB is valid.  */
302 
303 static int
bpscm_is_valid(breakpoint_smob * bp_smob)304 bpscm_is_valid (breakpoint_smob *bp_smob)
305 {
306   return bp_smob->bp != NULL;
307 }
308 
309 /* Returns the breakpoint smob in SELF, verifying it's valid.
310    Throws an exception if SELF is not a <gdb:breakpoint> object,
311    or is invalid.  */
312 
313 static breakpoint_smob *
bpscm_get_valid_breakpoint_smob_arg_unsafe(SCM self,int arg_pos,const char * func_name)314 bpscm_get_valid_breakpoint_smob_arg_unsafe (SCM self, int arg_pos,
315 					    const char *func_name)
316 {
317   breakpoint_smob *bp_smob
318     = bpscm_get_breakpoint_smob_arg_unsafe (self, arg_pos, func_name);
319 
320   if (!bpscm_is_valid (bp_smob))
321     {
322       gdbscm_invalid_object_error (func_name, arg_pos, self,
323 				   _("<gdb:breakpoint>"));
324     }
325 
326   return bp_smob;
327 }
328 
329 /* Breakpoint methods.  */
330 
331 /* (make-breakpoint string [#:type integer] [#:wp-class integer]
332     [#:internal boolean) -> <gdb:breakpoint>
333 
334    The result is the <gdb:breakpoint> Scheme object.
335    The breakpoint is not available to be used yet, however.
336    It must still be added to gdb with register-breakpoint!.  */
337 
338 static SCM
gdbscm_make_breakpoint(SCM location_scm,SCM rest)339 gdbscm_make_breakpoint (SCM location_scm, SCM rest)
340 {
341   const SCM keywords[] = {
342     type_keyword, wp_class_keyword, internal_keyword, SCM_BOOL_F
343   };
344   char *s;
345   char *location;
346   int type_arg_pos = -1, access_type_arg_pos = -1, internal_arg_pos = -1;
347   enum bptype type = bp_breakpoint;
348   enum target_hw_bp_type access_type = hw_write;
349   int internal = 0;
350   SCM result;
351   breakpoint_smob *bp_smob;
352 
353   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "s#iit",
354 			      location_scm, &location, rest,
355 			      &type_arg_pos, &type,
356 			      &access_type_arg_pos, &access_type,
357 			      &internal_arg_pos, &internal);
358 
359   result = bpscm_make_breakpoint_smob ();
360   bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (result);
361 
362   s = location;
363   location = gdbscm_gc_xstrdup (s);
364   xfree (s);
365 
366   switch (type)
367     {
368     case bp_breakpoint:
369       if (access_type_arg_pos > 0)
370 	{
371 	  gdbscm_misc_error (FUNC_NAME, access_type_arg_pos,
372 			     scm_from_int (access_type),
373 			     _("access type with breakpoint is not allowed"));
374 	}
375       break;
376     case bp_watchpoint:
377       switch (access_type)
378 	{
379 	case hw_write:
380 	case hw_access:
381 	case hw_read:
382 	  break;
383 	default:
384 	  gdbscm_out_of_range_error (FUNC_NAME, access_type_arg_pos,
385 				     scm_from_int (access_type),
386 				     _("invalid watchpoint class"));
387 	}
388       break;
389     default:
390       gdbscm_out_of_range_error (FUNC_NAME, access_type_arg_pos,
391 				 scm_from_int (type),
392 				 _("invalid breakpoint type"));
393     }
394 
395   bp_smob->is_scheme_bkpt = 1;
396   bp_smob->spec.location = location;
397   bp_smob->spec.type = type;
398   bp_smob->spec.access_type = access_type;
399   bp_smob->spec.is_internal = internal;
400 
401   return result;
402 }
403 
404 /* (register-breakpoint! <gdb:breakpoint>) -> unspecified
405 
406    It is an error to register a breakpoint created outside of Guile,
407    or an already-registered breakpoint.  */
408 
409 static SCM
gdbscm_register_breakpoint_x(SCM self)410 gdbscm_register_breakpoint_x (SCM self)
411 {
412   breakpoint_smob *bp_smob
413     = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
414   gdbscm_gdb_exception except {};
415   const char *location, *copy;
416 
417   /* We only support registering breakpoints created with make-breakpoint.  */
418   if (!bp_smob->is_scheme_bkpt)
419     scm_misc_error (FUNC_NAME, _("not a Scheme breakpoint"), SCM_EOL);
420 
421   if (bpscm_is_valid (bp_smob))
422     scm_misc_error (FUNC_NAME, _("breakpoint is already registered"), SCM_EOL);
423 
424   pending_breakpoint_scm = self;
425   location = bp_smob->spec.location;
426   copy = skip_spaces (location);
427   event_location_up eloc
428     = string_to_event_location_basic (&copy,
429 				      current_language,
430 				      symbol_name_match_type::WILD);
431 
432   try
433     {
434       int internal = bp_smob->spec.is_internal;
435 
436       switch (bp_smob->spec.type)
437 	{
438 	case bp_breakpoint:
439 	  {
440 	    const breakpoint_ops *ops =
441 	      breakpoint_ops_for_event_location (eloc.get (), false);
442 	    create_breakpoint (get_current_arch (),
443 			       eloc.get (), NULL, -1, NULL,
444 			       0,
445 			       0, bp_breakpoint,
446 			       0,
447 			       AUTO_BOOLEAN_TRUE,
448 			       ops,
449 			       0, 1, internal, 0);
450 	    break;
451 	  }
452 	case bp_watchpoint:
453 	  {
454 	    enum target_hw_bp_type access_type = bp_smob->spec.access_type;
455 
456 	    if (access_type == hw_write)
457 	      watch_command_wrapper (location, 0, internal);
458 	    else if (access_type == hw_access)
459 	      awatch_command_wrapper (location, 0, internal);
460 	    else if (access_type == hw_read)
461 	      rwatch_command_wrapper (location, 0, internal);
462 	    else
463 	      gdb_assert_not_reached ("invalid access type");
464 	    break;
465 	  }
466 	default:
467 	  gdb_assert_not_reached ("invalid breakpoint type");
468 	}
469     }
470   catch (const gdb_exception &ex)
471     {
472       except = unpack (ex);
473     }
474 
475   /* Ensure this gets reset, even if there's an error.  */
476   pending_breakpoint_scm = SCM_BOOL_F;
477   GDBSCM_HANDLE_GDB_EXCEPTION (except);
478 
479   return SCM_UNSPECIFIED;
480 }
481 
482 /* (delete-breakpoint! <gdb:breakpoint>) -> unspecified
483    Scheme function which deletes (removes) the underlying GDB breakpoint
484    from GDB's list of breakpoints.  This triggers the breakpoint_deleted
485    observer which will call gdbscm_breakpoint_deleted; that function cleans
486    up the Scheme bits.  */
487 
488 static SCM
gdbscm_delete_breakpoint_x(SCM self)489 gdbscm_delete_breakpoint_x (SCM self)
490 {
491   breakpoint_smob *bp_smob
492     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
493 
494   gdbscm_gdb_exception exc {};
495   try
496     {
497       delete_breakpoint (bp_smob->bp);
498     }
499   catch (const gdb_exception &except)
500     {
501       exc = unpack (except);
502     }
503 
504   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
505   return SCM_UNSPECIFIED;
506 }
507 
508 /* iterate_over_breakpoints function for gdbscm_breakpoints.  */
509 
510 static bool
bpscm_build_bp_list(struct breakpoint * bp,SCM * list)511 bpscm_build_bp_list (struct breakpoint *bp, SCM *list)
512 {
513   breakpoint_smob *bp_smob = bp->scm_bp_object;
514 
515   /* Lazily create wrappers for breakpoints created outside Scheme.  */
516 
517   if (bp_smob == NULL)
518     {
519       if (bpscm_want_scm_wrapper_p (bp, 0))
520 	{
521 	  SCM bp_scm;
522 
523 	  bp_scm = bpscm_make_breakpoint_smob ();
524 	  bpscm_attach_scm_to_breakpoint (bp, bp_scm);
525 	  /* Refetch it.  */
526 	  bp_smob = bp->scm_bp_object;
527 	}
528     }
529 
530   /* Not all breakpoints will have a companion Scheme object.
531      Only breakpoints that trigger the created_breakpoint observer call,
532      and satisfy certain conditions (see bpscm_want_scm_wrapper_p),
533      get a companion object (this includes Scheme-created breakpoints).  */
534 
535   if (bp_smob != NULL)
536     *list = scm_cons (bp_smob->containing_scm, *list);
537 
538   return false;
539 }
540 
541 /* (breakpoints) -> list
542    Return a list of all breakpoints.  */
543 
544 static SCM
gdbscm_breakpoints(void)545 gdbscm_breakpoints (void)
546 {
547   SCM list = SCM_EOL;
548 
549   iterate_over_breakpoints ([&] (breakpoint *bp)
550     {
551       return bpscm_build_bp_list(bp, &list);
552     });
553 
554   return scm_reverse_x (list, SCM_EOL);
555 }
556 
557 /* (breakpoint-valid? <gdb:breakpoint>) -> boolean
558    Returns #t if SELF is still valid.  */
559 
560 static SCM
gdbscm_breakpoint_valid_p(SCM self)561 gdbscm_breakpoint_valid_p (SCM self)
562 {
563   breakpoint_smob *bp_smob
564     = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
565 
566   return scm_from_bool (bpscm_is_valid (bp_smob));
567 }
568 
569 /* (breakpoint-enabled? <gdb:breakpoint>) -> boolean */
570 
571 static SCM
gdbscm_breakpoint_enabled_p(SCM self)572 gdbscm_breakpoint_enabled_p (SCM self)
573 {
574   breakpoint_smob *bp_smob
575     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
576 
577   return scm_from_bool (bp_smob->bp->enable_state == bp_enabled);
578 }
579 
580 /* (set-breakpoint-enabled? <gdb:breakpoint> boolean) -> unspecified */
581 
582 static SCM
gdbscm_set_breakpoint_enabled_x(SCM self,SCM newvalue)583 gdbscm_set_breakpoint_enabled_x (SCM self, SCM newvalue)
584 {
585   breakpoint_smob *bp_smob
586     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
587 
588   SCM_ASSERT_TYPE (gdbscm_is_bool (newvalue), newvalue, SCM_ARG2, FUNC_NAME,
589 		   _("boolean"));
590 
591   gdbscm_gdb_exception exc {};
592   try
593     {
594       if (gdbscm_is_true (newvalue))
595 	enable_breakpoint (bp_smob->bp);
596       else
597 	disable_breakpoint (bp_smob->bp);
598     }
599   catch (const gdb_exception &except)
600     {
601       exc = unpack (except);
602     }
603 
604   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
605   return SCM_UNSPECIFIED;
606 }
607 
608 /* (breakpoint-silent? <gdb:breakpoint>) -> boolean */
609 
610 static SCM
gdbscm_breakpoint_silent_p(SCM self)611 gdbscm_breakpoint_silent_p (SCM self)
612 {
613   breakpoint_smob *bp_smob
614     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
615 
616   return scm_from_bool (bp_smob->bp->silent);
617 }
618 
619 /* (set-breakpoint-silent?! <gdb:breakpoint> boolean) -> unspecified */
620 
621 static SCM
gdbscm_set_breakpoint_silent_x(SCM self,SCM newvalue)622 gdbscm_set_breakpoint_silent_x (SCM self, SCM newvalue)
623 {
624   breakpoint_smob *bp_smob
625     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
626 
627   SCM_ASSERT_TYPE (gdbscm_is_bool (newvalue), newvalue, SCM_ARG2, FUNC_NAME,
628 		   _("boolean"));
629 
630   gdbscm_gdb_exception exc {};
631   try
632     {
633       breakpoint_set_silent (bp_smob->bp, gdbscm_is_true (newvalue));
634     }
635   catch (const gdb_exception &except)
636     {
637       exc = unpack (except);
638     }
639 
640   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
641   return SCM_UNSPECIFIED;
642 }
643 
644 /* (breakpoint-ignore-count <gdb:breakpoint>) -> integer */
645 
646 static SCM
gdbscm_breakpoint_ignore_count(SCM self)647 gdbscm_breakpoint_ignore_count (SCM self)
648 {
649   breakpoint_smob *bp_smob
650     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
651 
652   return scm_from_long (bp_smob->bp->ignore_count);
653 }
654 
655 /* (set-breakpoint-ignore-count! <gdb:breakpoint> integer)
656      -> unspecified */
657 
658 static SCM
gdbscm_set_breakpoint_ignore_count_x(SCM self,SCM newvalue)659 gdbscm_set_breakpoint_ignore_count_x (SCM self, SCM newvalue)
660 {
661   breakpoint_smob *bp_smob
662     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
663   long value;
664 
665   SCM_ASSERT_TYPE (scm_is_signed_integer (newvalue, LONG_MIN, LONG_MAX),
666 		   newvalue, SCM_ARG2, FUNC_NAME, _("integer"));
667 
668   value = scm_to_long (newvalue);
669   if (value < 0)
670     value = 0;
671 
672   gdbscm_gdb_exception exc {};
673   try
674     {
675       set_ignore_count (bp_smob->number, (int) value, 0);
676     }
677   catch (const gdb_exception &except)
678     {
679       exc = unpack (except);
680     }
681 
682   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
683   return SCM_UNSPECIFIED;
684 }
685 
686 /* (breakpoint-hit-count <gdb:breakpoint>) -> integer */
687 
688 static SCM
gdbscm_breakpoint_hit_count(SCM self)689 gdbscm_breakpoint_hit_count (SCM self)
690 {
691   breakpoint_smob *bp_smob
692     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
693 
694   return scm_from_long (bp_smob->bp->hit_count);
695 }
696 
697 /* (set-breakpoint-hit-count! <gdb:breakpoint> integer) -> unspecified */
698 
699 static SCM
gdbscm_set_breakpoint_hit_count_x(SCM self,SCM newvalue)700 gdbscm_set_breakpoint_hit_count_x (SCM self, SCM newvalue)
701 {
702   breakpoint_smob *bp_smob
703     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
704   long value;
705 
706   SCM_ASSERT_TYPE (scm_is_signed_integer (newvalue, LONG_MIN, LONG_MAX),
707 		   newvalue, SCM_ARG2, FUNC_NAME, _("integer"));
708 
709   value = scm_to_long (newvalue);
710   if (value < 0)
711     value = 0;
712 
713   if (value != 0)
714     {
715       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, newvalue,
716 				 _("hit-count must be zero"));
717     }
718 
719   bp_smob->bp->hit_count = 0;
720 
721   return SCM_UNSPECIFIED;
722 }
723 
724 /* (breakpoint-thread <gdb:breakpoint>) -> integer */
725 
726 static SCM
gdbscm_breakpoint_thread(SCM self)727 gdbscm_breakpoint_thread (SCM self)
728 {
729   breakpoint_smob *bp_smob
730     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
731 
732   if (bp_smob->bp->thread == -1)
733     return SCM_BOOL_F;
734 
735   return scm_from_long (bp_smob->bp->thread);
736 }
737 
738 /* (set-breakpoint-thread! <gdb:breakpoint> integer) -> unspecified */
739 
740 static SCM
gdbscm_set_breakpoint_thread_x(SCM self,SCM newvalue)741 gdbscm_set_breakpoint_thread_x (SCM self, SCM newvalue)
742 {
743   breakpoint_smob *bp_smob
744     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
745   long id;
746 
747   if (scm_is_signed_integer (newvalue, LONG_MIN, LONG_MAX))
748     {
749       id = scm_to_long (newvalue);
750       if (!valid_global_thread_id (id))
751 	{
752 	  gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, newvalue,
753 				     _("invalid thread id"));
754 	}
755     }
756   else if (gdbscm_is_false (newvalue))
757     id = -1;
758   else
759     SCM_ASSERT_TYPE (0, newvalue, SCM_ARG2, FUNC_NAME, _("integer or #f"));
760 
761   breakpoint_set_thread (bp_smob->bp, id);
762 
763   return SCM_UNSPECIFIED;
764 }
765 
766 /* (breakpoint-task <gdb:breakpoint>) -> integer */
767 
768 static SCM
gdbscm_breakpoint_task(SCM self)769 gdbscm_breakpoint_task (SCM self)
770 {
771   breakpoint_smob *bp_smob
772     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
773 
774   if (bp_smob->bp->task == 0)
775     return SCM_BOOL_F;
776 
777   return scm_from_long (bp_smob->bp->task);
778 }
779 
780 /* (set-breakpoint-task! <gdb:breakpoint> integer) -> unspecified */
781 
782 static SCM
gdbscm_set_breakpoint_task_x(SCM self,SCM newvalue)783 gdbscm_set_breakpoint_task_x (SCM self, SCM newvalue)
784 {
785   breakpoint_smob *bp_smob
786     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
787   long id;
788   int valid_id = 0;
789 
790   if (scm_is_signed_integer (newvalue, LONG_MIN, LONG_MAX))
791     {
792       id = scm_to_long (newvalue);
793 
794       gdbscm_gdb_exception exc {};
795       try
796 	{
797 	  valid_id = valid_task_id (id);
798 	}
799       catch (const gdb_exception &except)
800 	{
801 	  exc = unpack (except);
802 	}
803 
804       GDBSCM_HANDLE_GDB_EXCEPTION (exc);
805       if (! valid_id)
806 	{
807 	  gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, newvalue,
808 				     _("invalid task id"));
809 	}
810     }
811   else if (gdbscm_is_false (newvalue))
812     id = 0;
813   else
814     SCM_ASSERT_TYPE (0, newvalue, SCM_ARG2, FUNC_NAME, _("integer or #f"));
815 
816   gdbscm_gdb_exception exc {};
817   try
818     {
819       breakpoint_set_task (bp_smob->bp, id);
820     }
821   catch (const gdb_exception &except)
822     {
823       exc = unpack (except);
824     }
825 
826   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
827   return SCM_UNSPECIFIED;
828 }
829 
830 /* (breakpoint-location <gdb:breakpoint>) -> string */
831 
832 static SCM
gdbscm_breakpoint_location(SCM self)833 gdbscm_breakpoint_location (SCM self)
834 {
835   breakpoint_smob *bp_smob
836     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
837   const char *str;
838 
839   if (bp_smob->bp->type != bp_breakpoint)
840     return SCM_BOOL_F;
841 
842   str = event_location_to_string (bp_smob->bp->location.get ());
843   if (! str)
844     str = "";
845 
846   return gdbscm_scm_from_c_string (str);
847 }
848 
849 /* (breakpoint-expression <gdb:breakpoint>) -> string
850    This is only valid for watchpoints.
851    Returns #f for non-watchpoints.  */
852 
853 static SCM
gdbscm_breakpoint_expression(SCM self)854 gdbscm_breakpoint_expression (SCM self)
855 {
856   breakpoint_smob *bp_smob
857     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
858   struct watchpoint *wp;
859 
860   if (!is_watchpoint (bp_smob->bp))
861     return SCM_BOOL_F;
862 
863   wp = (struct watchpoint *) bp_smob->bp;
864 
865   const char *str = wp->exp_string;
866   if (! str)
867     str = "";
868 
869   return gdbscm_scm_from_c_string (str);
870 }
871 
872 /* (breakpoint-condition <gdb:breakpoint>) -> string */
873 
874 static SCM
gdbscm_breakpoint_condition(SCM self)875 gdbscm_breakpoint_condition (SCM self)
876 {
877   breakpoint_smob *bp_smob
878     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
879   char *str;
880 
881   str = bp_smob->bp->cond_string;
882   if (! str)
883     return SCM_BOOL_F;
884 
885   return gdbscm_scm_from_c_string (str);
886 }
887 
888 /* (set-breakpoint-condition! <gdb:breakpoint> string|#f)
889    -> unspecified */
890 
891 static SCM
gdbscm_set_breakpoint_condition_x(SCM self,SCM newvalue)892 gdbscm_set_breakpoint_condition_x (SCM self, SCM newvalue)
893 {
894   breakpoint_smob *bp_smob
895     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
896 
897   SCM_ASSERT_TYPE (scm_is_string (newvalue) || gdbscm_is_false (newvalue),
898 		   newvalue, SCM_ARG2, FUNC_NAME,
899 		   _("string or #f"));
900 
901   return gdbscm_wrap ([=]
902     {
903       gdb::unique_xmalloc_ptr<char> exp
904 	= (gdbscm_is_false (newvalue)
905 	   ? nullptr
906 	   : gdbscm_scm_to_c_string (newvalue));
907 
908       set_breakpoint_condition (bp_smob->bp, exp ? exp.get () : "", 0);
909 
910       return SCM_UNSPECIFIED;
911     });
912 }
913 
914 /* (breakpoint-stop <gdb:breakpoint>) -> procedure or #f */
915 
916 static SCM
gdbscm_breakpoint_stop(SCM self)917 gdbscm_breakpoint_stop (SCM self)
918 {
919   breakpoint_smob *bp_smob
920     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
921 
922   return bp_smob->stop;
923 }
924 
925 /* (set-breakpoint-stop! <gdb:breakpoint> procedure|#f)
926    -> unspecified */
927 
928 static SCM
gdbscm_set_breakpoint_stop_x(SCM self,SCM newvalue)929 gdbscm_set_breakpoint_stop_x (SCM self, SCM newvalue)
930 {
931   breakpoint_smob *bp_smob
932     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
933   const struct extension_language_defn *extlang = NULL;
934 
935   SCM_ASSERT_TYPE (gdbscm_is_procedure (newvalue)
936 		   || gdbscm_is_false (newvalue),
937 		   newvalue, SCM_ARG2, FUNC_NAME,
938 		   _("procedure or #f"));
939 
940   if (bp_smob->bp->cond_string != NULL)
941     extlang = get_ext_lang_defn (EXT_LANG_GDB);
942   if (extlang == NULL)
943     extlang = get_breakpoint_cond_ext_lang (bp_smob->bp, EXT_LANG_GUILE);
944   if (extlang != NULL)
945     {
946       char *error_text
947 	= xstrprintf (_("Only one stop condition allowed.  There is"
948 			" currently a %s stop condition defined for"
949 			" this breakpoint."),
950 		      ext_lang_capitalized_name (extlang));
951 
952       scm_dynwind_begin ((scm_t_dynwind_flags) 0);
953       gdbscm_dynwind_xfree (error_text);
954       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self, error_text);
955       /* The following line, while unnecessary, is present for completeness
956 	 sake.  */
957       scm_dynwind_end ();
958     }
959 
960   bp_smob->stop = newvalue;
961 
962   return SCM_UNSPECIFIED;
963 }
964 
965 /* (breakpoint-commands <gdb:breakpoint>) -> string */
966 
967 static SCM
gdbscm_breakpoint_commands(SCM self)968 gdbscm_breakpoint_commands (SCM self)
969 {
970   breakpoint_smob *bp_smob
971     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
972   struct breakpoint *bp;
973   SCM result;
974 
975   bp = bp_smob->bp;
976 
977   if (bp->commands == NULL)
978     return SCM_BOOL_F;
979 
980   string_file buf;
981 
982   current_uiout->redirect (&buf);
983   gdbscm_gdb_exception exc {};
984   try
985     {
986       print_command_lines (current_uiout, breakpoint_commands (bp), 0);
987     }
988   catch (const gdb_exception &except)
989     {
990       exc = unpack (except);
991     }
992 
993   current_uiout->redirect (NULL);
994   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
995   result = gdbscm_scm_from_c_string (buf.c_str ());
996 
997   return result;
998 }
999 
1000 /* (breakpoint-type <gdb:breakpoint>) -> integer */
1001 
1002 static SCM
gdbscm_breakpoint_type(SCM self)1003 gdbscm_breakpoint_type (SCM self)
1004 {
1005   breakpoint_smob *bp_smob
1006     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
1007 
1008   return scm_from_long (bp_smob->bp->type);
1009 }
1010 
1011 /* (breakpoint-visible? <gdb:breakpoint>) -> boolean */
1012 
1013 static SCM
gdbscm_breakpoint_visible(SCM self)1014 gdbscm_breakpoint_visible (SCM self)
1015 {
1016   breakpoint_smob *bp_smob
1017     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
1018 
1019   return scm_from_bool (bp_smob->bp->number >= 0);
1020 }
1021 
1022 /* (breakpoint-number <gdb:breakpoint>) -> integer */
1023 
1024 static SCM
gdbscm_breakpoint_number(SCM self)1025 gdbscm_breakpoint_number (SCM self)
1026 {
1027   breakpoint_smob *bp_smob
1028     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
1029 
1030   return scm_from_long (bp_smob->number);
1031 }
1032 
1033 /* Return TRUE if "stop" has been set for this breakpoint.
1034 
1035    This is the extension_language_ops.breakpoint_has_cond "method".  */
1036 
1037 int
gdbscm_breakpoint_has_cond(const struct extension_language_defn * extlang,struct breakpoint * b)1038 gdbscm_breakpoint_has_cond (const struct extension_language_defn *extlang,
1039 			    struct breakpoint *b)
1040 {
1041   breakpoint_smob *bp_smob = b->scm_bp_object;
1042 
1043   if (bp_smob == NULL)
1044     return 0;
1045 
1046   return gdbscm_is_procedure (bp_smob->stop);
1047 }
1048 
1049 /* Call the "stop" method in the breakpoint class.
1050    This must only be called if gdbscm_breakpoint_has_cond returns true.
1051    If the stop method returns #t, the inferior will be stopped at the
1052    breakpoint.  Otherwise the inferior will be allowed to continue
1053    (assuming other conditions don't indicate "stop").
1054 
1055    This is the extension_language_ops.breakpoint_cond_says_stop "method".  */
1056 
1057 enum ext_lang_bp_stop
gdbscm_breakpoint_cond_says_stop(const struct extension_language_defn * extlang,struct breakpoint * b)1058 gdbscm_breakpoint_cond_says_stop
1059   (const struct extension_language_defn *extlang, struct breakpoint *b)
1060 {
1061   breakpoint_smob *bp_smob = b->scm_bp_object;
1062   SCM predicate_result;
1063   int stop;
1064 
1065   if (bp_smob == NULL)
1066     return EXT_LANG_BP_STOP_UNSET;
1067   if (!gdbscm_is_procedure (bp_smob->stop))
1068     return EXT_LANG_BP_STOP_UNSET;
1069 
1070   stop = 1;
1071 
1072   predicate_result
1073     = gdbscm_safe_call_1 (bp_smob->stop, bp_smob->containing_scm, NULL);
1074 
1075   if (gdbscm_is_exception (predicate_result))
1076     ; /* Exception already printed.  */
1077   /* If the "stop" function returns #f that means
1078      the Scheme breakpoint wants GDB to continue.  */
1079   else if (gdbscm_is_false (predicate_result))
1080     stop = 0;
1081 
1082   return stop ? EXT_LANG_BP_STOP_YES : EXT_LANG_BP_STOP_NO;
1083 }
1084 
1085 /* Event callback functions.  */
1086 
1087 /* Callback that is used when a breakpoint is created.
1088    For breakpoints created by Scheme, i.e., gdbscm_create_breakpoint_x, finish
1089    object creation by connecting the Scheme wrapper to the gdb object.
1090    We ignore breakpoints created from gdb or python here, we create the
1091    Scheme wrapper for those when there's a need to, e.g.,
1092    gdbscm_breakpoints.  */
1093 
1094 static void
bpscm_breakpoint_created(struct breakpoint * bp)1095 bpscm_breakpoint_created (struct breakpoint *bp)
1096 {
1097   SCM bp_scm;
1098 
1099   if (gdbscm_is_false (pending_breakpoint_scm))
1100     return;
1101 
1102   /* Verify our caller error checked the user's request.  */
1103   gdb_assert (bpscm_want_scm_wrapper_p (bp, 1));
1104 
1105   bp_scm = pending_breakpoint_scm;
1106   pending_breakpoint_scm = SCM_BOOL_F;
1107 
1108   bpscm_attach_scm_to_breakpoint (bp, bp_scm);
1109 }
1110 
1111 /* Callback that is used when a breakpoint is deleted.  This will
1112    invalidate the corresponding Scheme object.  */
1113 
1114 static void
bpscm_breakpoint_deleted(struct breakpoint * b)1115 bpscm_breakpoint_deleted (struct breakpoint *b)
1116 {
1117   int num = b->number;
1118   struct breakpoint *bp;
1119 
1120   /* TODO: Why the lookup?  We have B.  */
1121 
1122   bp = get_breakpoint (num);
1123   if (bp)
1124     {
1125       breakpoint_smob *bp_smob = bp->scm_bp_object;
1126 
1127       if (bp_smob)
1128 	{
1129 	  bp_smob->bp = NULL;
1130 	  bp_smob->number = -1;
1131 	  bp_smob->stop = SCM_BOOL_F;
1132 	  scm_gc_unprotect_object (bp_smob->containing_scm);
1133 	}
1134     }
1135 }
1136 
1137 /* Initialize the Scheme breakpoint code.  */
1138 
1139 static const scheme_integer_constant breakpoint_integer_constants[] =
1140 {
1141   { "BP_NONE", bp_none },
1142   { "BP_BREAKPOINT", bp_breakpoint },
1143   { "BP_WATCHPOINT", bp_watchpoint },
1144   { "BP_HARDWARE_WATCHPOINT", bp_hardware_watchpoint },
1145   { "BP_READ_WATCHPOINT", bp_read_watchpoint },
1146   { "BP_ACCESS_WATCHPOINT", bp_access_watchpoint },
1147 
1148   { "WP_READ", hw_read },
1149   { "WP_WRITE", hw_write },
1150   { "WP_ACCESS", hw_access },
1151 
1152   END_INTEGER_CONSTANTS
1153 };
1154 
1155 static const scheme_function breakpoint_functions[] =
1156 {
1157   { "make-breakpoint", 1, 0, 1, as_a_scm_t_subr (gdbscm_make_breakpoint),
1158     "\
1159 Create a GDB breakpoint object.\n\
1160 \n\
1161   Arguments:\n\
1162     location [#:type <type>] [#:wp-class <wp-class>] [#:internal <bool>]\n\
1163   Returns:\n\
1164     <gdb:breakpoint object" },
1165 
1166   { "register-breakpoint!", 1, 0, 0,
1167     as_a_scm_t_subr (gdbscm_register_breakpoint_x),
1168     "\
1169 Register a <gdb:breakpoint> object with GDB." },
1170 
1171   { "delete-breakpoint!", 1, 0, 0, as_a_scm_t_subr (gdbscm_delete_breakpoint_x),
1172     "\
1173 Delete the breakpoint from GDB." },
1174 
1175   { "breakpoints", 0, 0, 0, as_a_scm_t_subr (gdbscm_breakpoints),
1176     "\
1177 Return a list of all GDB breakpoints.\n\
1178 \n\
1179   Arguments: none" },
1180 
1181   { "breakpoint?", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_p),
1182     "\
1183 Return #t if the object is a <gdb:breakpoint> object." },
1184 
1185   { "breakpoint-valid?", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_valid_p),
1186     "\
1187 Return #t if the breakpoint has not been deleted from GDB." },
1188 
1189   { "breakpoint-number", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_number),
1190     "\
1191 Return the breakpoint's number." },
1192 
1193   { "breakpoint-type", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_type),
1194     "\
1195 Return the type of the breakpoint." },
1196 
1197   { "breakpoint-visible?", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_visible),
1198     "\
1199 Return #t if the breakpoint is visible to the user." },
1200 
1201   { "breakpoint-location", 1, 0, 0,
1202     as_a_scm_t_subr (gdbscm_breakpoint_location),
1203     "\
1204 Return the location of the breakpoint as specified by the user." },
1205 
1206   { "breakpoint-expression", 1, 0, 0,
1207     as_a_scm_t_subr (gdbscm_breakpoint_expression),
1208     "\
1209 Return the expression of the breakpoint as specified by the user.\n\
1210 Valid for watchpoints only, returns #f for non-watchpoints." },
1211 
1212   { "breakpoint-enabled?", 1, 0, 0,
1213     as_a_scm_t_subr (gdbscm_breakpoint_enabled_p),
1214     "\
1215 Return #t if the breakpoint is enabled." },
1216 
1217   { "set-breakpoint-enabled!", 2, 0, 0,
1218     as_a_scm_t_subr (gdbscm_set_breakpoint_enabled_x),
1219     "\
1220 Set the breakpoint's enabled state.\n\
1221 \n\
1222   Arguments: <gdb:breakpoint> boolean" },
1223 
1224   { "breakpoint-silent?", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_silent_p),
1225     "\
1226 Return #t if the breakpoint is silent." },
1227 
1228   { "set-breakpoint-silent!", 2, 0, 0,
1229     as_a_scm_t_subr (gdbscm_set_breakpoint_silent_x),
1230     "\
1231 Set the breakpoint's silent state.\n\
1232 \n\
1233   Arguments: <gdb:breakpoint> boolean" },
1234 
1235   { "breakpoint-ignore-count", 1, 0, 0,
1236     as_a_scm_t_subr (gdbscm_breakpoint_ignore_count),
1237     "\
1238 Return the breakpoint's \"ignore\" count." },
1239 
1240   { "set-breakpoint-ignore-count!", 2, 0, 0,
1241     as_a_scm_t_subr (gdbscm_set_breakpoint_ignore_count_x),
1242     "\
1243 Set the breakpoint's \"ignore\" count.\n\
1244 \n\
1245   Arguments: <gdb:breakpoint> count" },
1246 
1247   { "breakpoint-hit-count", 1, 0, 0,
1248     as_a_scm_t_subr (gdbscm_breakpoint_hit_count),
1249     "\
1250 Return the breakpoint's \"hit\" count." },
1251 
1252   { "set-breakpoint-hit-count!", 2, 0, 0,
1253     as_a_scm_t_subr (gdbscm_set_breakpoint_hit_count_x),
1254     "\
1255 Set the breakpoint's \"hit\" count.  The value must be zero.\n\
1256 \n\
1257   Arguments: <gdb:breakpoint> 0" },
1258 
1259   { "breakpoint-thread", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_thread),
1260     "\
1261 Return the breakpoint's global thread id or #f if there isn't one." },
1262 
1263   { "set-breakpoint-thread!", 2, 0, 0,
1264     as_a_scm_t_subr (gdbscm_set_breakpoint_thread_x),
1265     "\
1266 Set the global thread id for this breakpoint.\n\
1267 \n\
1268   Arguments: <gdb:breakpoint> global-thread-id" },
1269 
1270   { "breakpoint-task", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_task),
1271     "\
1272 Return the breakpoint's Ada task-id or #f if there isn't one." },
1273 
1274   { "set-breakpoint-task!", 2, 0, 0,
1275     as_a_scm_t_subr (gdbscm_set_breakpoint_task_x),
1276     "\
1277 Set the breakpoint's Ada task-id.\n\
1278 \n\
1279   Arguments: <gdb:breakpoint> task-id" },
1280 
1281   { "breakpoint-condition", 1, 0, 0,
1282     as_a_scm_t_subr (gdbscm_breakpoint_condition),
1283     "\
1284 Return the breakpoint's condition as specified by the user.\n\
1285 Return #f if there isn't one." },
1286 
1287   { "set-breakpoint-condition!", 2, 0, 0,
1288     as_a_scm_t_subr (gdbscm_set_breakpoint_condition_x),
1289     "\
1290 Set the breakpoint's condition.\n\
1291 \n\
1292   Arguments: <gdb:breakpoint> condition\n\
1293     condition: a string" },
1294 
1295   { "breakpoint-stop", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_stop),
1296     "\
1297 Return the breakpoint's stop predicate.\n\
1298 Return #f if there isn't one." },
1299 
1300   { "set-breakpoint-stop!", 2, 0, 0,
1301     as_a_scm_t_subr (gdbscm_set_breakpoint_stop_x),
1302     "\
1303 Set the breakpoint's stop predicate.\n\
1304 \n\
1305   Arguments: <gdb:breakpoint> procedure\n\
1306     procedure: A procedure of one argument, the breakpoint.\n\
1307       Its result is true if program execution should stop." },
1308 
1309   { "breakpoint-commands", 1, 0, 0,
1310     as_a_scm_t_subr (gdbscm_breakpoint_commands),
1311     "\
1312 Return the breakpoint's commands." },
1313 
1314   END_FUNCTIONS
1315 };
1316 
1317 void
gdbscm_initialize_breakpoints(void)1318 gdbscm_initialize_breakpoints (void)
1319 {
1320   breakpoint_smob_tag
1321     = gdbscm_make_smob_type (breakpoint_smob_name, sizeof (breakpoint_smob));
1322   scm_set_smob_free (breakpoint_smob_tag, bpscm_free_breakpoint_smob);
1323   scm_set_smob_print (breakpoint_smob_tag, bpscm_print_breakpoint_smob);
1324 
1325   gdb::observers::breakpoint_created.attach (bpscm_breakpoint_created);
1326   gdb::observers::breakpoint_deleted.attach (bpscm_breakpoint_deleted);
1327 
1328   gdbscm_define_integer_constants (breakpoint_integer_constants, 1);
1329   gdbscm_define_functions (breakpoint_functions, 1);
1330 
1331   type_keyword = scm_from_latin1_keyword ("type");
1332   wp_class_keyword = scm_from_latin1_keyword ("wp-class");
1333   internal_keyword = scm_from_latin1_keyword ("internal");
1334 }
1335