Add Python support for hardware breakpoints
[deliverable/binutils-gdb.git] / gdb / python / py-breakpoint.c
CommitLineData
adc36818
PM
1/* Python interface to breakpoints
2
3666a048 3 Copyright (C) 2008-2021 Free Software Foundation, Inc.
adc36818
PM
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 "value.h"
adc36818 22#include "python-internal.h"
49a8461d 23#include "python.h"
adc36818
PM
24#include "charset.h"
25#include "breakpoint.h"
26#include "gdbcmd.h"
27#include "gdbthread.h"
76727919 28#include "observable.h"
adc36818
PM
29#include "cli/cli-script.h"
30#include "ada-lang.h"
7371cf6d
PM
31#include "arch-utils.h"
32#include "language.h"
f00aae0f 33#include "location.h"
dac790e1 34#include "py-event.h"
824cc835 35#include "linespec.h"
adc36818 36
adc36818
PM
37/* Number of live breakpoints. */
38static int bppy_live;
39
40/* Variables used to pass information between the Breakpoint
41 constructor and the breakpoint-created hook function. */
4cb0213d 42gdbpy_breakpoint_object *bppy_pending_object;
adc36818 43
7371cf6d 44/* Function that is called when a Python condition is evaluated. */
a121b7c1 45static const char stop_func[] = "stop";
7371cf6d 46
adc36818
PM
47/* This is used to initialize various gdb.bp_* constants. */
48struct pybp_code
49{
50 /* The name. */
51 const char *name;
52 /* The code. */
e81b7af8 53 int code;
adc36818
PM
54};
55
56/* Entries related to the type of user set breakpoints. */
57static struct pybp_code pybp_codes[] =
58{
59 { "BP_NONE", bp_none},
60 { "BP_BREAKPOINT", bp_breakpoint},
325d39e4 61 { "BP_HARDWARE_BREAKPOINT", bp_hardware_breakpoint},
adc36818
PM
62 { "BP_WATCHPOINT", bp_watchpoint},
63 { "BP_HARDWARE_WATCHPOINT", bp_hardware_watchpoint},
64 { "BP_READ_WATCHPOINT", bp_read_watchpoint},
65 { "BP_ACCESS_WATCHPOINT", bp_access_watchpoint},
66 {NULL} /* Sentinel. */
67};
68
69/* Entries related to the type of watchpoint. */
70static struct pybp_code pybp_watch_types[] =
71{
72 { "WP_READ", hw_read},
73 { "WP_WRITE", hw_write},
74 { "WP_ACCESS", hw_access},
75 {NULL} /* Sentinel. */
76};
77
adc36818
PM
78/* Python function which checks the validity of a breakpoint object. */
79static PyObject *
80bppy_is_valid (PyObject *self, PyObject *args)
81{
4cb0213d 82 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
83
84 if (self_bp->bp)
85 Py_RETURN_TRUE;
86 Py_RETURN_FALSE;
87}
88
89/* Python function to test whether or not the breakpoint is enabled. */
90static PyObject *
91bppy_get_enabled (PyObject *self, void *closure)
92{
4cb0213d 93 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
94
95 BPPY_REQUIRE_VALID (self_bp);
96 if (! self_bp->bp)
97 Py_RETURN_FALSE;
98 if (self_bp->bp->enable_state == bp_enabled)
99 Py_RETURN_TRUE;
100 Py_RETURN_FALSE;
101}
102
103/* Python function to test whether or not the breakpoint is silent. */
104static PyObject *
105bppy_get_silent (PyObject *self, void *closure)
106{
4cb0213d 107 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
108
109 BPPY_REQUIRE_VALID (self_bp);
110 if (self_bp->bp->silent)
111 Py_RETURN_TRUE;
112 Py_RETURN_FALSE;
113}
114
115/* Python function to set the enabled state of a breakpoint. */
116static int
117bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure)
118{
4cb0213d 119 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
120 int cmp;
121
122 BPPY_SET_REQUIRE_VALID (self_bp);
123
124 if (newvalue == NULL)
125 {
256458bc 126 PyErr_SetString (PyExc_TypeError,
adc36818
PM
127 _("Cannot delete `enabled' attribute."));
128
129 return -1;
130 }
131 else if (! PyBool_Check (newvalue))
132 {
133 PyErr_SetString (PyExc_TypeError,
134 _("The value of `enabled' must be a boolean."));
135 return -1;
136 }
137
138 cmp = PyObject_IsTrue (newvalue);
139 if (cmp < 0)
140 return -1;
76dce0be 141
a70b8144 142 try
76dce0be
PM
143 {
144 if (cmp == 1)
145 enable_breakpoint (self_bp->bp);
146 else
147 disable_breakpoint (self_bp->bp);
148 }
230d2906 149 catch (const gdb_exception &except)
492d29ea
PA
150 {
151 GDB_PY_SET_HANDLE_EXCEPTION (except);
152 }
76dce0be 153
adc36818
PM
154 return 0;
155}
156
157/* Python function to set the 'silent' state of a breakpoint. */
158static int
159bppy_set_silent (PyObject *self, PyObject *newvalue, void *closure)
160{
4cb0213d 161 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
162 int cmp;
163
164 BPPY_SET_REQUIRE_VALID (self_bp);
165
166 if (newvalue == NULL)
167 {
256458bc 168 PyErr_SetString (PyExc_TypeError,
adc36818
PM
169 _("Cannot delete `silent' attribute."));
170 return -1;
171 }
172 else if (! PyBool_Check (newvalue))
173 {
174 PyErr_SetString (PyExc_TypeError,
175 _("The value of `silent' must be a boolean."));
176 return -1;
177 }
178
179 cmp = PyObject_IsTrue (newvalue);
180 if (cmp < 0)
181 return -1;
182 else
45a43567 183 breakpoint_set_silent (self_bp->bp, cmp);
adc36818
PM
184
185 return 0;
186}
187
188/* Python function to set the thread of a breakpoint. */
189static int
190bppy_set_thread (PyObject *self, PyObject *newvalue, void *closure)
191{
4cb0213d 192 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
74aedc46 193 long id;
adc36818
PM
194
195 BPPY_SET_REQUIRE_VALID (self_bp);
196
197 if (newvalue == NULL)
198 {
256458bc 199 PyErr_SetString (PyExc_TypeError,
adc36818
PM
200 _("Cannot delete `thread' attribute."));
201 return -1;
202 }
203 else if (PyInt_Check (newvalue))
204 {
74aedc46
TT
205 if (! gdb_py_int_as_long (newvalue, &id))
206 return -1;
207
5d5658a1 208 if (!valid_global_thread_id (id))
adc36818 209 {
256458bc 210 PyErr_SetString (PyExc_RuntimeError,
adc36818
PM
211 _("Invalid thread ID."));
212 return -1;
213 }
214 }
215 else if (newvalue == Py_None)
216 id = -1;
217 else
218 {
219 PyErr_SetString (PyExc_TypeError,
220 _("The value of `thread' must be an integer or None."));
221 return -1;
222 }
223
45a43567 224 breakpoint_set_thread (self_bp->bp, id);
adc36818
PM
225
226 return 0;
227}
228
229/* Python function to set the (Ada) task of a breakpoint. */
230static int
231bppy_set_task (PyObject *self, PyObject *newvalue, void *closure)
232{
4cb0213d 233 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
74aedc46 234 long id;
76dce0be 235 int valid_id = 0;
adc36818
PM
236
237 BPPY_SET_REQUIRE_VALID (self_bp);
238
239 if (newvalue == NULL)
240 {
256458bc 241 PyErr_SetString (PyExc_TypeError,
adc36818
PM
242 _("Cannot delete `task' attribute."));
243 return -1;
244 }
245 else if (PyInt_Check (newvalue))
246 {
74aedc46
TT
247 if (! gdb_py_int_as_long (newvalue, &id))
248 return -1;
249
a70b8144 250 try
76dce0be
PM
251 {
252 valid_id = valid_task_id (id);
253 }
230d2906 254 catch (const gdb_exception &except)
492d29ea
PA
255 {
256 GDB_PY_SET_HANDLE_EXCEPTION (except);
257 }
76dce0be
PM
258
259 if (! valid_id)
adc36818 260 {
256458bc 261 PyErr_SetString (PyExc_RuntimeError,
adc36818
PM
262 _("Invalid task ID."));
263 return -1;
264 }
265 }
266 else if (newvalue == Py_None)
267 id = 0;
268 else
269 {
270 PyErr_SetString (PyExc_TypeError,
271 _("The value of `task' must be an integer or None."));
272 return -1;
273 }
274
45a43567 275 breakpoint_set_task (self_bp->bp, id);
adc36818
PM
276
277 return 0;
278}
279
94b6973e
PM
280/* Python function which deletes the underlying GDB breakpoint. This
281 triggers the breakpoint_deleted observer which will call
282 gdbpy_breakpoint_deleted; that function cleans up the Python
283 sections. */
284
285static PyObject *
286bppy_delete_breakpoint (PyObject *self, PyObject *args)
287{
4cb0213d 288 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
94b6973e
PM
289
290 BPPY_REQUIRE_VALID (self_bp);
291
a70b8144 292 try
76dce0be
PM
293 {
294 delete_breakpoint (self_bp->bp);
295 }
230d2906 296 catch (const gdb_exception &except)
492d29ea
PA
297 {
298 GDB_PY_HANDLE_EXCEPTION (except);
299 }
94b6973e
PM
300
301 Py_RETURN_NONE;
302}
303
adc36818
PM
304
305/* Python function to set the ignore count of a breakpoint. */
306static int
307bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure)
308{
4cb0213d 309 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
310 long value;
311
312 BPPY_SET_REQUIRE_VALID (self_bp);
313
314 if (newvalue == NULL)
315 {
316 PyErr_SetString (PyExc_TypeError,
317 _("Cannot delete `ignore_count' attribute."));
318 return -1;
319 }
320 else if (! PyInt_Check (newvalue))
321 {
322 PyErr_SetString (PyExc_TypeError,
323 _("The value of `ignore_count' must be an integer."));
324 return -1;
325 }
326
74aedc46
TT
327 if (! gdb_py_int_as_long (newvalue, &value))
328 return -1;
329
adc36818
PM
330 if (value < 0)
331 value = 0;
5d9c5995 332
a70b8144 333 try
5d9c5995
PM
334 {
335 set_ignore_count (self_bp->number, (int) value, 0);
336 }
230d2906 337 catch (const gdb_exception &except)
492d29ea
PA
338 {
339 GDB_PY_SET_HANDLE_EXCEPTION (except);
340 }
adc36818
PM
341
342 return 0;
343}
344
345/* Python function to set the hit count of a breakpoint. */
346static int
347bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure)
348{
4cb0213d 349 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
350
351 BPPY_SET_REQUIRE_VALID (self_bp);
352
353 if (newvalue == NULL)
354 {
256458bc 355 PyErr_SetString (PyExc_TypeError,
adc36818
PM
356 _("Cannot delete `hit_count' attribute."));
357 return -1;
358 }
74aedc46 359 else
adc36818 360 {
74aedc46
TT
361 long value;
362
363 if (! gdb_py_int_as_long (newvalue, &value))
364 return -1;
365
366 if (value != 0)
367 {
368 PyErr_SetString (PyExc_AttributeError,
369 _("The value of `hit_count' must be zero."));
370 return -1;
371 }
adc36818
PM
372 }
373
374 self_bp->bp->hit_count = 0;
375
376 return 0;
377}
378
379/* Python function to get the location of a breakpoint. */
380static PyObject *
381bppy_get_location (PyObject *self, void *closure)
382{
4cb0213d 383 gdbpy_breakpoint_object *obj = (gdbpy_breakpoint_object *) self;
adc36818
PM
384
385 BPPY_REQUIRE_VALID (obj);
386
325d39e4
HD
387 if (obj->bp->type != bp_breakpoint
388 && obj->bp->type != bp_hardware_breakpoint)
adc36818
PM
389 Py_RETURN_NONE;
390
cb1e4e32 391 const char *str = event_location_to_string (obj->bp->location.get ());
adc36818
PM
392 if (! str)
393 str = "";
833d985d 394 return host_string_to_python_string (str).release ();
adc36818
PM
395}
396
397/* Python function to get the breakpoint expression. */
398static PyObject *
399bppy_get_expression (PyObject *self, void *closure)
400{
a121b7c1 401 const char *str;
4cb0213d 402 gdbpy_breakpoint_object *obj = (gdbpy_breakpoint_object *) self;
3a5c3e22 403 struct watchpoint *wp;
adc36818
PM
404
405 BPPY_REQUIRE_VALID (obj);
406
3a5c3e22 407 if (!is_watchpoint (obj->bp))
adc36818
PM
408 Py_RETURN_NONE;
409
3a5c3e22
PA
410 wp = (struct watchpoint *) obj->bp;
411
412 str = wp->exp_string;
adc36818
PM
413 if (! str)
414 str = "";
415
833d985d 416 return host_string_to_python_string (str).release ();
adc36818
PM
417}
418
419/* Python function to get the condition expression of a breakpoint. */
420static PyObject *
421bppy_get_condition (PyObject *self, void *closure)
422{
423 char *str;
4cb0213d 424 gdbpy_breakpoint_object *obj = (gdbpy_breakpoint_object *) self;
adc36818
PM
425
426 BPPY_REQUIRE_VALID (obj);
427
428 str = obj->bp->cond_string;
429 if (! str)
430 Py_RETURN_NONE;
431
833d985d 432 return host_string_to_python_string (str).release ();
adc36818
PM
433}
434
8dc78533
JK
435/* Returns 0 on success. Returns -1 on error, with a python exception set.
436 */
437
adc36818
PM
438static int
439bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
440{
9b972014
TT
441 gdb::unique_xmalloc_ptr<char> exp_holder;
442 const char *exp = NULL;
4cb0213d 443 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
cc06b668 444 struct gdb_exception except;
adc36818
PM
445
446 BPPY_SET_REQUIRE_VALID (self_bp);
447
448 if (newvalue == NULL)
449 {
256458bc 450 PyErr_SetString (PyExc_TypeError,
adc36818
PM
451 _("Cannot delete `condition' attribute."));
452 return -1;
453 }
454 else if (newvalue == Py_None)
455 exp = "";
456 else
457 {
9b972014
TT
458 exp_holder = python_string_to_host_string (newvalue);
459 if (exp_holder == NULL)
adc36818 460 return -1;
9b972014 461 exp = exp_holder.get ();
adc36818
PM
462 }
463
a70b8144 464 try
adc36818 465 {
733d554a 466 set_breakpoint_condition (self_bp->bp, exp, 0, false);
adc36818 467 }
94aeb44b 468 catch (gdb_exception &ex)
492d29ea 469 {
94aeb44b 470 except = std::move (ex);
492d29ea 471 }
f3be5b64 472
adc36818
PM
473 GDB_PY_SET_HANDLE_EXCEPTION (except);
474
475 return 0;
476}
477
478/* Python function to get the commands attached to a breakpoint. */
479static PyObject *
480bppy_get_commands (PyObject *self, void *closure)
481{
4cb0213d 482 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818 483 struct breakpoint *bp = self_bp->bp;
adc36818
PM
484
485 BPPY_REQUIRE_VALID (self_bp);
486
487 if (! self_bp->bp->commands)
488 Py_RETURN_NONE;
489
d7e74731 490 string_file stb;
adc36818 491
d7e74731 492 current_uiout->redirect (&stb);
a70b8144 493 try
adc36818 494 {
79a45e25 495 print_command_lines (current_uiout, breakpoint_commands (bp), 0);
adc36818 496 }
230d2906 497 catch (const gdb_exception &except)
b862ce75 498 {
112e8700 499 current_uiout->redirect (NULL);
f3300387
TT
500 gdbpy_convert_exception (except);
501 return NULL;
b862ce75 502 }
adc36818 503
112e8700 504 current_uiout->redirect (NULL);
833d985d 505 return host_string_to_python_string (stb.c_str ()).release ();
adc36818
PM
506}
507
a913fffb
TT
508/* Set the commands attached to a breakpoint. Returns 0 on success.
509 Returns -1 on error, with a python exception set. */
510static int
511bppy_set_commands (PyObject *self, PyObject *newvalue, void *closure)
512{
513 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
cc06b668 514 struct gdb_exception except;
a913fffb
TT
515
516 BPPY_SET_REQUIRE_VALID (self_bp);
517
518 gdb::unique_xmalloc_ptr<char> commands
519 (python_string_to_host_string (newvalue));
520 if (commands == nullptr)
521 return -1;
522
a70b8144 523 try
a913fffb
TT
524 {
525 bool first = true;
526 char *save_ptr = nullptr;
527 auto reader
528 = [&] ()
529 {
530 const char *result = strtok_r (first ? commands.get () : nullptr,
531 "\n", &save_ptr);
532 first = false;
533 return result;
534 };
535
536 counted_command_line lines = read_command_lines_1 (reader, 1, nullptr);
537 breakpoint_set_commands (self_bp->bp, std::move (lines));
538 }
94aeb44b 539 catch (gdb_exception &ex)
a913fffb 540 {
94aeb44b 541 except = std::move (ex);
a913fffb 542 }
a913fffb
TT
543
544 GDB_PY_SET_HANDLE_EXCEPTION (except);
545
546 return 0;
547}
548
adc36818
PM
549/* Python function to get the breakpoint type. */
550static PyObject *
551bppy_get_type (PyObject *self, void *closure)
552{
4cb0213d 553 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
554
555 BPPY_REQUIRE_VALID (self_bp);
556
47f0e2ff 557 return gdb_py_object_from_longest (self_bp->bp->type).release ();
adc36818
PM
558}
559
84f4c1fe
PM
560/* Python function to get the visibility of the breakpoint. */
561
562static PyObject *
563bppy_get_visibility (PyObject *self, void *closure)
564{
4cb0213d 565 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
84f4c1fe
PM
566
567 BPPY_REQUIRE_VALID (self_bp);
568
43684a7b
TT
569 if (user_breakpoint_p (self_bp->bp))
570 Py_RETURN_TRUE;
84f4c1fe 571
43684a7b 572 Py_RETURN_FALSE;
84f4c1fe
PM
573}
574
f76c27b5
PM
575/* Python function to determine if the breakpoint is a temporary
576 breakpoint. */
577
578static PyObject *
579bppy_get_temporary (PyObject *self, void *closure)
580{
4cb0213d 581 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
f76c27b5
PM
582
583 BPPY_REQUIRE_VALID (self_bp);
584
585 if (self_bp->bp->disposition == disp_del
586 || self_bp->bp->disposition == disp_del_at_next_stop)
587 Py_RETURN_TRUE;
588
589 Py_RETURN_FALSE;
590}
591
93daf339
TT
592/* Python function to determine if the breakpoint is a pending
593 breakpoint. */
594
595static PyObject *
596bppy_get_pending (PyObject *self, void *closure)
597{
598 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
599
600 BPPY_REQUIRE_VALID (self_bp);
601
602 if (is_watchpoint (self_bp->bp))
603 Py_RETURN_FALSE;
604 if (pending_breakpoint_p (self_bp->bp))
605 Py_RETURN_TRUE;
606
607 Py_RETURN_FALSE;
608}
609
adc36818
PM
610/* Python function to get the breakpoint's number. */
611static PyObject *
612bppy_get_number (PyObject *self, void *closure)
613{
4cb0213d 614 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
615
616 BPPY_REQUIRE_VALID (self_bp);
617
47f0e2ff 618 return gdb_py_object_from_longest (self_bp->number).release ();
adc36818
PM
619}
620
621/* Python function to get the breakpoint's thread ID. */
622static PyObject *
623bppy_get_thread (PyObject *self, void *closure)
624{
4cb0213d 625 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
626
627 BPPY_REQUIRE_VALID (self_bp);
628
629 if (self_bp->bp->thread == -1)
630 Py_RETURN_NONE;
631
47f0e2ff 632 return gdb_py_object_from_longest (self_bp->bp->thread).release ();
adc36818
PM
633}
634
635/* Python function to get the breakpoint's task ID (in Ada). */
636static PyObject *
637bppy_get_task (PyObject *self, void *closure)
638{
4cb0213d 639 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
640
641 BPPY_REQUIRE_VALID (self_bp);
642
643 if (self_bp->bp->task == 0)
644 Py_RETURN_NONE;
645
47f0e2ff 646 return gdb_py_object_from_longest (self_bp->bp->task).release ();
adc36818
PM
647}
648
649/* Python function to get the breakpoint's hit count. */
650static PyObject *
651bppy_get_hit_count (PyObject *self, void *closure)
652{
4cb0213d 653 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
654
655 BPPY_REQUIRE_VALID (self_bp);
656
47f0e2ff 657 return gdb_py_object_from_longest (self_bp->bp->hit_count).release ();
adc36818
PM
658}
659
660/* Python function to get the breakpoint's ignore count. */
661static PyObject *
662bppy_get_ignore_count (PyObject *self, void *closure)
663{
4cb0213d 664 gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
adc36818
PM
665
666 BPPY_REQUIRE_VALID (self_bp);
667
47f0e2ff 668 return gdb_py_object_from_longest (self_bp->bp->ignore_count).release ();
adc36818
PM
669}
670
824cc835
PM
671/* Internal function to validate the Python parameters/keywords
672 provided to bppy_init. */
673
674static int
675bppy_init_validate_args (const char *spec, char *source,
676 char *function, char *label,
677 char *line, enum bptype type)
678{
679 /* If spec is defined, ensure that none of the explicit location
680 keywords are also defined. */
681 if (spec != NULL)
682 {
683 if (source != NULL || function != NULL || label != NULL || line != NULL)
684 {
685 PyErr_SetString (PyExc_RuntimeError,
686 _("Breakpoints specified with spec cannot "
687 "have source, function, label or line defined."));
688 return -1;
689 }
690 }
691 else
692 {
693 /* If spec isn't defined, ensure that the user is not trying to
694 define a watchpoint with an explicit location. */
695 if (type == bp_watchpoint)
696 {
697 PyErr_SetString (PyExc_RuntimeError,
698 _("Watchpoints cannot be set by explicit "
699 "location parameters."));
700 return -1;
701 }
702 else
703 {
704 /* Otherwise, ensure some explicit locations are defined. */
705 if (source == NULL && function == NULL && label == NULL
706 && line == NULL)
707 {
708 PyErr_SetString (PyExc_RuntimeError,
709 _("Neither spec nor explicit location set."));
710 return -1;
711 }
712 /* Finally, if source is specified, ensure that line, label
713 or function are specified too. */
714 if (source != NULL && function == NULL && label == NULL
715 && line == NULL)
716 {
717 PyErr_SetString (PyExc_RuntimeError,
718 _("Specifying a source must also include a "
719 "line, label or function."));
720 return -1;
721 }
722 }
723 }
724 return 1;
725}
726
adc36818 727/* Python function to create a new breakpoint. */
7371cf6d
PM
728static int
729bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
adc36818 730{
2adadf51 731 static const char *keywords[] = { "spec", "type", "wp_class", "internal",
824cc835 732 "temporary","source", "function",
b89641ba 733 "label", "line", "qualified", NULL };
824cc835
PM
734 const char *spec = NULL;
735 enum bptype type = bp_breakpoint;
adc36818 736 int access_type = hw_write;
84f4c1fe 737 PyObject *internal = NULL;
f76c27b5 738 PyObject *temporary = NULL;
824cc835 739 PyObject *lineobj = NULL;;
84f4c1fe 740 int internal_bp = 0;
f76c27b5 741 int temporary_bp = 0;
824cc835
PM
742 gdb::unique_xmalloc_ptr<char> line;
743 char *label = NULL;
744 char *source = NULL;
745 char *function = NULL;
8e557e52 746 PyObject * qualified = NULL;
adc36818 747
8e557e52 748 if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssOO", keywords,
2adadf51 749 &spec, &type, &access_type,
824cc835
PM
750 &internal,
751 &temporary, &source,
b89641ba
SM
752 &function, &label, &lineobj,
753 &qualified))
7371cf6d 754 return -1;
adc36818 755
824cc835
PM
756
757 if (lineobj != NULL)
758 {
759 if (PyInt_Check (lineobj))
760 line.reset (xstrprintf ("%ld", PyInt_AsLong (lineobj)));
761 else if (PyString_Check (lineobj))
762 line = python_string_to_host_string (lineobj);
763 else
764 {
765 PyErr_SetString (PyExc_RuntimeError,
766 _("Line keyword should be an integer or a string. "));
767 return -1;
768 }
769 }
770
84f4c1fe
PM
771 if (internal)
772 {
773 internal_bp = PyObject_IsTrue (internal);
774 if (internal_bp == -1)
7371cf6d 775 return -1;
84f4c1fe
PM
776 }
777
f76c27b5
PM
778 if (temporary != NULL)
779 {
780 temporary_bp = PyObject_IsTrue (temporary);
781 if (temporary_bp == -1)
782 return -1;
783 }
784
824cc835
PM
785 if (bppy_init_validate_args (spec, source, function, label, line.get (),
786 type) == -1)
787 return -1;
788
4cb0213d 789 bppy_pending_object = (gdbpy_breakpoint_object *) self;
adc36818
PM
790 bppy_pending_object->number = -1;
791 bppy_pending_object->bp = NULL;
256458bc 792
a70b8144 793 try
adc36818
PM
794 {
795 switch (type)
796 {
797 case bp_breakpoint:
325d39e4 798 case bp_hardware_breakpoint:
adc36818 799 {
824cc835 800 event_location_up location;
b89641ba 801 symbol_name_match_type func_name_match_type
8e557e52 802 = (qualified != NULL && PyObject_IsTrue (qualified)
b89641ba
SM
803 ? symbol_name_match_type::FULL
804 : symbol_name_match_type::WILD);
824cc835
PM
805
806 if (spec != NULL)
807 {
808 gdb::unique_xmalloc_ptr<char>
809 copy_holder (xstrdup (skip_spaces (spec)));
810 const char *copy = copy_holder.get ();
811
812 location = string_to_event_location (&copy,
b89641ba
SM
813 current_language,
814 func_name_match_type);
824cc835
PM
815 }
816 else
817 {
818 struct explicit_location explicit_loc;
819
820 initialize_explicit_location (&explicit_loc);
821 explicit_loc.source_filename = source;
822 explicit_loc.function_name = function;
823 explicit_loc.label_name = label;
824
825 if (line != NULL)
826 explicit_loc.line_offset =
827 linespec_parse_line_offset (line.get ());
828
b89641ba
SM
829 explicit_loc.func_name_match_type = func_name_match_type;
830
824cc835
PM
831 location = new_explicit_location (&explicit_loc);
832 }
833
bac7c5cf
GB
834 const struct breakpoint_ops *ops =
835 breakpoint_ops_for_event_location (location.get (), false);
836
adc36818 837 create_breakpoint (python_gdbarch,
ffc2605c 838 location.get (), NULL, -1, NULL,
adc36818 839 0,
325d39e4 840 temporary_bp, type,
adc36818
PM
841 0,
842 AUTO_BOOLEAN_TRUE,
bac7c5cf 843 ops,
44f238bb 844 0, 1, internal_bp, 0);
adc36818
PM
845 break;
846 }
824cc835 847 case bp_watchpoint:
adc36818 848 {
824cc835
PM
849 gdb::unique_xmalloc_ptr<char>
850 copy_holder (xstrdup (skip_spaces (spec)));
851 char *copy = copy_holder.get ();
852
adc36818 853 if (access_type == hw_write)
ddd49eee 854 watch_command_wrapper (copy, 0, internal_bp);
adc36818 855 else if (access_type == hw_access)
ddd49eee 856 awatch_command_wrapper (copy, 0, internal_bp);
adc36818 857 else if (access_type == hw_read)
ddd49eee 858 rwatch_command_wrapper (copy, 0, internal_bp);
adc36818
PM
859 else
860 error(_("Cannot understand watchpoint access type."));
861 break;
862 }
863 default:
864 error(_("Do not understand breakpoint type to set."));
865 }
866 }
230d2906 867 catch (const gdb_exception &except)
adc36818 868 {
f4952523 869 bppy_pending_object = NULL;
ec9c2750 870 gdbpy_convert_exception (except);
7371cf6d 871 return -1;
adc36818
PM
872 }
873
4cb0213d 874 BPPY_SET_REQUIRE_VALID ((gdbpy_breakpoint_object *) self);
7371cf6d 875 return 0;
adc36818
PM
876}
877
878\f
879
95da600f
CB
880static bool
881build_bp_list (struct breakpoint *b, PyObject *list)
84f4c1fe 882{
50389644 883 PyObject *bp = (PyObject *) b->py_bp_object;
84f4c1fe
PM
884 int iserr = 0;
885
886 /* Not all breakpoints will have a companion Python object.
887 Only breakpoints that were created via bppy_new, or
888 breakpoints that were created externally and are tracked by
889 the Python Scripting API. */
890 if (bp)
891 iserr = PyList_Append (list, bp);
892
893 if (iserr == -1)
95da600f 894 return true;
84f4c1fe 895
95da600f 896 return false;
84f4c1fe
PM
897}
898
adc36818
PM
899/* Static function to return a tuple holding all breakpoints. */
900
901PyObject *
902gdbpy_breakpoints (PyObject *self, PyObject *args)
903{
adc36818 904 if (bppy_live == 0)
1957f6b8 905 return PyTuple_New (0);
adc36818 906
7780f186 907 gdbpy_ref<> list (PyList_New (0));
bf2a52fa 908 if (list == NULL)
84f4c1fe 909 return NULL;
d59b6f6c 910
1957f6b8 911 /* If iterate_over_breakpoints returns non NULL it signals an error
84f4c1fe
PM
912 condition. In that case abandon building the list and return
913 NULL. */
95da600f
CB
914 auto callback = [&] (breakpoint *bp)
915 {
916 return build_bp_list(bp, list.get ());
917 };
918 if (iterate_over_breakpoints (callback) != NULL)
bf2a52fa 919 return NULL;
27ca1a5b 920
bf2a52fa 921 return PyList_AsTuple (list.get ());
adc36818
PM
922}
923
7371cf6d
PM
924/* Call the "stop" method (if implemented) in the breakpoint
925 class. If the method returns True, the inferior will be
926 stopped at the breakpoint. Otherwise the inferior will be
927 allowed to continue. */
928
6dddc817
DE
929enum ext_lang_bp_stop
930gdbpy_breakpoint_cond_says_stop (const struct extension_language_defn *extlang,
931 struct breakpoint *b)
7371cf6d 932{
6dddc817
DE
933 int stop;
934 struct gdbpy_breakpoint_object *bp_obj = b->py_bp_object;
7371cf6d 935 PyObject *py_bp = (PyObject *) bp_obj;
6dddc817 936 struct gdbarch *garch;
6dddc817
DE
937
938 if (bp_obj == NULL)
939 return EXT_LANG_BP_STOP_UNSET;
940
941 stop = -1;
942 garch = b->gdbarch ? b->gdbarch : get_current_arch ();
de2dc875
TT
943
944 gdbpy_enter enter_py (garch, current_language);
7371cf6d 945
cc72b2a2
KP
946 if (bp_obj->is_finish_bp)
947 bpfinishpy_pre_stop_hook (bp_obj);
948
7371cf6d
PM
949 if (PyObject_HasAttrString (py_bp, stop_func))
950 {
7780f186 951 gdbpy_ref<> result (PyObject_CallMethod (py_bp, stop_func, NULL));
7371cf6d 952
6dddc817 953 stop = 1;
64081434 954 if (result != NULL)
7371cf6d 955 {
64081434 956 int evaluate = PyObject_IsTrue (result.get ());
7371cf6d
PM
957
958 if (evaluate == -1)
959 gdbpy_print_stack ();
960
961 /* If the "stop" function returns False that means
962 the Python breakpoint wants GDB to continue. */
963 if (! evaluate)
964 stop = 0;
7371cf6d
PM
965 }
966 else
967 gdbpy_print_stack ();
968 }
cc72b2a2
KP
969
970 if (bp_obj->is_finish_bp)
971 bpfinishpy_post_stop_hook (bp_obj);
972
6dddc817
DE
973 if (stop < 0)
974 return EXT_LANG_BP_STOP_UNSET;
975 return stop ? EXT_LANG_BP_STOP_YES : EXT_LANG_BP_STOP_NO;
7371cf6d
PM
976}
977
978/* Checks if the "stop" method exists in this breakpoint.
979 Used by condition_command to ensure mutual exclusion of breakpoint
980 conditions. */
981
982int
6dddc817
DE
983gdbpy_breakpoint_has_cond (const struct extension_language_defn *extlang,
984 struct breakpoint *b)
7371cf6d 985{
6dddc817
DE
986 PyObject *py_bp;
987 struct gdbarch *garch;
256458bc 988
6dddc817
DE
989 if (b->py_bp_object == NULL)
990 return 0;
7371cf6d 991
6dddc817
DE
992 py_bp = (PyObject *) b->py_bp_object;
993 garch = b->gdbarch ? b->gdbarch : get_current_arch ();
7371cf6d 994
de2dc875
TT
995 gdbpy_enter enter_py (garch, current_language);
996 return PyObject_HasAttrString (py_bp, stop_func);
7371cf6d
PM
997}
998
adc36818
PM
999\f
1000
1001/* Event callback functions. */
1002
1003/* Callback that is used when a breakpoint is created. This function
1004 will create a new Python breakpoint object. */
1005static void
8d3788bd 1006gdbpy_breakpoint_created (struct breakpoint *bp)
adc36818 1007{
4cb0213d 1008 gdbpy_breakpoint_object *newbp;
adc36818 1009
43684a7b 1010 if (!user_breakpoint_p (bp) && bppy_pending_object == NULL)
84f4c1fe
PM
1011 return;
1012
256458bc 1013 if (bp->type != bp_breakpoint
325d39e4 1014 && bp->type != bp_hardware_breakpoint
adc36818 1015 && bp->type != bp_watchpoint
256458bc 1016 && bp->type != bp_hardware_watchpoint
adc36818
PM
1017 && bp->type != bp_read_watchpoint
1018 && bp->type != bp_access_watchpoint)
1019 return;
1020
25ce02ee
TT
1021 struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
1022 gdbpy_enter enter_py (garch, current_language);
adc36818
PM
1023
1024 if (bppy_pending_object)
1025 {
1026 newbp = bppy_pending_object;
bd454f8b 1027 Py_INCREF (newbp);
adc36818
PM
1028 bppy_pending_object = NULL;
1029 }
1030 else
4cb0213d 1031 newbp = PyObject_New (gdbpy_breakpoint_object, &breakpoint_object_type);
adc36818
PM
1032 if (newbp)
1033 {
8d3788bd 1034 newbp->number = bp->number;
adc36818 1035 newbp->bp = bp;
50389644 1036 newbp->bp->py_bp_object = newbp;
cc72b2a2 1037 newbp->is_finish_bp = 0;
84f4c1fe
PM
1038 ++bppy_live;
1039 }
1040 else
1041 {
1042 PyErr_SetString (PyExc_RuntimeError,
1043 _("Error while creating breakpoint from GDB."));
1044 gdbpy_print_stack ();
adc36818 1045 }
adc36818 1046
dac790e1
TT
1047 if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_created))
1048 {
dac790e1
TT
1049 if (evpy_emit_event ((PyObject *) newbp,
1050 gdb_py_events.breakpoint_created) < 0)
1051 gdbpy_print_stack ();
1052 }
adc36818
PM
1053}
1054
1055/* Callback that is used when a breakpoint is deleted. This will
1056 invalidate the corresponding Python object. */
1057static void
8d3788bd 1058gdbpy_breakpoint_deleted (struct breakpoint *b)
adc36818 1059{
8d3788bd 1060 int num = b->number;
84f4c1fe 1061 struct breakpoint *bp = NULL;
adc36818 1062
84f4c1fe 1063 bp = get_breakpoint (num);
d930d06e 1064 if (bp)
adc36818 1065 {
25ce02ee
TT
1066 struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
1067 gdbpy_enter enter_py (garch, current_language);
1068
88b6faea
TT
1069 gdbpy_ref<gdbpy_breakpoint_object> bp_obj (bp->py_bp_object);
1070 if (bp_obj != NULL)
d930d06e 1071 {
dac790e1
TT
1072 if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_deleted))
1073 {
88b6faea 1074 if (evpy_emit_event ((PyObject *) bp_obj.get (),
dac790e1
TT
1075 gdb_py_events.breakpoint_deleted) < 0)
1076 gdbpy_print_stack ();
1077 }
1078
d930d06e
TT
1079 bp_obj->bp = NULL;
1080 --bppy_live;
d930d06e 1081 }
adc36818 1082 }
adc36818
PM
1083}
1084
dac790e1
TT
1085/* Callback that is used when a breakpoint is modified. */
1086
1087static void
1088gdbpy_breakpoint_modified (struct breakpoint *b)
1089{
1090 int num = b->number;
dac790e1 1091 struct breakpoint *bp = NULL;
dac790e1 1092
dac790e1
TT
1093 bp = get_breakpoint (num);
1094 if (bp)
1095 {
25ce02ee
TT
1096 struct gdbarch *garch = bp->gdbarch ? bp->gdbarch : get_current_arch ();
1097 gdbpy_enter enter_py (garch, current_language);
1098
dac790e1
TT
1099 PyObject *bp_obj = (PyObject *) bp->py_bp_object;
1100 if (bp_obj)
1101 {
1102 if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_modified))
1103 {
dac790e1
TT
1104 if (evpy_emit_event (bp_obj,
1105 gdb_py_events.breakpoint_modified) < 0)
1106 gdbpy_print_stack ();
1107 }
1108 }
1109 }
dac790e1
TT
1110}
1111
adc36818
PM
1112\f
1113
1114/* Initialize the Python breakpoint code. */
999633ed 1115int
adc36818
PM
1116gdbpy_initialize_breakpoints (void)
1117{
1118 int i;
1119
6a1b1664 1120 breakpoint_object_type.tp_new = PyType_GenericNew;
adc36818 1121 if (PyType_Ready (&breakpoint_object_type) < 0)
999633ed 1122 return -1;
adc36818 1123
aa36459a
TT
1124 if (gdb_pymodule_addobject (gdb_module, "Breakpoint",
1125 (PyObject *) &breakpoint_object_type) < 0)
999633ed 1126 return -1;
adc36818 1127
76727919
TT
1128 gdb::observers::breakpoint_created.attach (gdbpy_breakpoint_created);
1129 gdb::observers::breakpoint_deleted.attach (gdbpy_breakpoint_deleted);
1130 gdb::observers::breakpoint_modified.attach (gdbpy_breakpoint_modified);
adc36818
PM
1131
1132 /* Add breakpoint types constants. */
1133 for (i = 0; pybp_codes[i].name; ++i)
1134 {
6c28e44a 1135 if (PyModule_AddIntConstant (gdb_module, pybp_codes[i].name,
adc36818 1136 pybp_codes[i].code) < 0)
999633ed 1137 return -1;
adc36818
PM
1138 }
1139
1140 /* Add watchpoint types constants. */
1141 for (i = 0; pybp_watch_types[i].name; ++i)
1142 {
6c28e44a 1143 if (PyModule_AddIntConstant (gdb_module, pybp_watch_types[i].name,
adc36818 1144 pybp_watch_types[i].code) < 0)
999633ed 1145 return -1;
adc36818
PM
1146 }
1147
999633ed 1148 return 0;
adc36818
PM
1149}
1150
1151\f
1152
7371cf6d
PM
1153/* Helper function that overrides this Python object's
1154 PyObject_GenericSetAttr to allow extra validation of the attribute
1155 being set. */
1156
256458bc 1157static int
7371cf6d
PM
1158local_setattro (PyObject *self, PyObject *name, PyObject *v)
1159{
256458bc 1160 gdbpy_breakpoint_object *obj = (gdbpy_breakpoint_object *) self;
9b972014 1161 gdb::unique_xmalloc_ptr<char> attr (python_string_to_host_string (name));
256458bc 1162
7371cf6d
PM
1163 if (attr == NULL)
1164 return -1;
256458bc 1165
7371cf6d 1166 /* If the attribute trying to be set is the "stop" method,
6dddc817
DE
1167 but we already have a condition set in the CLI or other extension
1168 language, disallow this operation. */
9b972014 1169 if (strcmp (attr.get (), stop_func) == 0)
7371cf6d 1170 {
6dddc817
DE
1171 const struct extension_language_defn *extlang = NULL;
1172
1173 if (obj->bp->cond_string != NULL)
1174 extlang = get_ext_lang_defn (EXT_LANG_GDB);
1175 if (extlang == NULL)
1176 extlang = get_breakpoint_cond_ext_lang (obj->bp, EXT_LANG_PYTHON);
1177 if (extlang != NULL)
1178 {
7f968c89
TT
1179 std::string error_text
1180 = string_printf (_("Only one stop condition allowed. There is"
1181 " currently a %s stop condition defined for"
1182 " this breakpoint."),
1183 ext_lang_capitalized_name (extlang));
1184 PyErr_SetString (PyExc_RuntimeError, error_text.c_str ());
6dddc817
DE
1185 return -1;
1186 }
7371cf6d 1187 }
256458bc 1188
8833fbf0 1189 return PyObject_GenericSetAttr (self, name, v);
7371cf6d
PM
1190}
1191
0d1f4ceb 1192static gdb_PyGetSetDef breakpoint_object_getset[] = {
adc36818
PM
1193 { "enabled", bppy_get_enabled, bppy_set_enabled,
1194 "Boolean telling whether the breakpoint is enabled.", NULL },
1195 { "silent", bppy_get_silent, bppy_set_silent,
1196 "Boolean telling whether the breakpoint is silent.", NULL },
1197 { "thread", bppy_get_thread, bppy_set_thread,
1198 "Thread ID for the breakpoint.\n\
1199If the value is a thread ID (integer), then this is a thread-specific breakpoint.\n\
1200If the value is None, then this breakpoint is not thread-specific.\n\
1201No other type of value can be used.", NULL },
1202 { "task", bppy_get_task, bppy_set_task,
1203 "Thread ID for the breakpoint.\n\
1204If the value is a task ID (integer), then this is an Ada task-specific breakpoint.\n\
1205If the value is None, then this breakpoint is not task-specific.\n\
1206No other type of value can be used.", NULL },
1207 { "ignore_count", bppy_get_ignore_count, bppy_set_ignore_count,
1208 "Number of times this breakpoint should be automatically continued.",
1209 NULL },
1210 { "number", bppy_get_number, NULL,
1211 "Breakpoint's number assigned by GDB.", NULL },
1212 { "hit_count", bppy_get_hit_count, bppy_set_hit_count,
1213 "Number of times the breakpoint has been hit.\n\
1214Can be set to zero to clear the count. No other value is valid\n\
1215when setting this property.", NULL },
1216 { "location", bppy_get_location, NULL,
1217 "Location of the breakpoint, as specified by the user.", NULL},
1218 { "expression", bppy_get_expression, NULL,
1219 "Expression of the breakpoint, as specified by the user.", NULL},
1220 { "condition", bppy_get_condition, bppy_set_condition,
1221 "Condition of the breakpoint, as specified by the user,\
1222or None if no condition set."},
a913fffb 1223 { "commands", bppy_get_commands, bppy_set_commands,
adc36818
PM
1224 "Commands of the breakpoint, as specified by the user."},
1225 { "type", bppy_get_type, NULL,
1226 "Type of breakpoint."},
84f4c1fe
PM
1227 { "visible", bppy_get_visibility, NULL,
1228 "Whether the breakpoint is visible to the user."},
f76c27b5
PM
1229 { "temporary", bppy_get_temporary, NULL,
1230 "Whether this breakpoint is a temporary breakpoint."},
93daf339
TT
1231 { "pending", bppy_get_pending, NULL,
1232 "Whether this breakpoint is a pending breakpoint."},
adc36818
PM
1233 { NULL } /* Sentinel. */
1234};
1235
1236static PyMethodDef breakpoint_object_methods[] =
1237{
1238 { "is_valid", bppy_is_valid, METH_NOARGS,
1239 "Return true if this breakpoint is valid, false if not." },
94b6973e
PM
1240 { "delete", bppy_delete_breakpoint, METH_NOARGS,
1241 "Delete the underlying GDB breakpoint." },
adc36818
PM
1242 { NULL } /* Sentinel. */
1243};
1244
cc72b2a2 1245PyTypeObject breakpoint_object_type =
adc36818 1246{
9a27f2c6 1247 PyVarObject_HEAD_INIT (NULL, 0)
adc36818 1248 "gdb.Breakpoint", /*tp_name*/
4cb0213d 1249 sizeof (gdbpy_breakpoint_object), /*tp_basicsize*/
adc36818
PM
1250 0, /*tp_itemsize*/
1251 0, /*tp_dealloc*/
1252 0, /*tp_print*/
1253 0, /*tp_getattr*/
1254 0, /*tp_setattr*/
1255 0, /*tp_compare*/
1256 0, /*tp_repr*/
1257 0, /*tp_as_number*/
1258 0, /*tp_as_sequence*/
1259 0, /*tp_as_mapping*/
1260 0, /*tp_hash */
1261 0, /*tp_call*/
1262 0, /*tp_str*/
1263 0, /*tp_getattro*/
7371cf6d 1264 (setattrofunc)local_setattro, /*tp_setattro */
adc36818 1265 0, /*tp_as_buffer*/
7371cf6d 1266 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
adc36818
PM
1267 "GDB breakpoint object", /* tp_doc */
1268 0, /* tp_traverse */
1269 0, /* tp_clear */
1270 0, /* tp_richcompare */
1271 0, /* tp_weaklistoffset */
1272 0, /* tp_iter */
1273 0, /* tp_iternext */
1274 breakpoint_object_methods, /* tp_methods */
1275 0, /* tp_members */
7371cf6d
PM
1276 breakpoint_object_getset, /* tp_getset */
1277 0, /* tp_base */
1278 0, /* tp_dict */
1279 0, /* tp_descr_get */
1280 0, /* tp_descr_set */
1281 0, /* tp_dictoffset */
1282 bppy_init, /* tp_init */
1283 0, /* tp_alloc */
adc36818 1284};
This page took 1.205878 seconds and 4 git commands to generate.