| |   |
| 1 | /* Python interface to breakpoints |
| 2 | |
| 3 | Copyright (C) 2008 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 | #include "defs.h" |
| 21 | #include "value.h" |
| 22 | #include "exceptions.h" |
| 23 | #include "python-internal.h" |
| 24 | #include "charset.h" |
| 25 | #include "breakpoint.h" |
| 26 | #include "gdbcmd.h" |
| 27 | |
| 28 | |
| 29 | /* From breakpoint.c. */ |
| 30 | extern struct breakpoint *breakpoint_chain; |
| 31 | |
| 32 | |
| 33 | typedef struct breakpoint_object breakpoint_object; |
| 34 | |
| 35 | static PyObject *bppy_is_valid (PyObject *, PyObject *); |
| 36 | static PyObject *bppy_is_enabled (PyObject *, PyObject *); |
| 37 | static PyObject *bppy_is_silent (PyObject *, PyObject *); |
| 38 | static PyObject *bppy_set_enabled (PyObject *, PyObject *); |
| 39 | static PyObject *bppy_set_silent (PyObject *, PyObject *); |
| 40 | static PyObject *bppy_get_location (PyObject *, PyObject *); |
| 41 | static PyObject *bppy_get_condition (PyObject *, PyObject *); |
| 42 | static PyObject *bppy_get_commands (PyObject *, PyObject *); |
| 43 | |
| 44 | |
| 45 | /* A dynamically allocated vector of breakpoint objects. Each |
| 46 | breakpoint has a number. A breakpoint is valid if its slot in this |
| 47 | vector is non-null. When a breakpoint is deleted, we drop our |
| 48 | reference to it and zero its slot; this is how we let the Python |
| 49 | object have a lifetime which is independent from that of the gdb |
| 50 | breakpoint. */ |
| 51 | static breakpoint_object **bppy_breakpoints; |
| 52 | |
| 53 | /* Number of slots in bppy_breakpoints. */ |
| 54 | static int bppy_slots; |
| 55 | |
| 56 | /* Number of live breakpoints. */ |
| 57 | static int bppy_live; |
| 58 | |
| 59 | /* Variables used to pass information between the Breakpoint |
| 60 | constructor and the breakpoint-created hook function. */ |
| 61 | static breakpoint_object *bppy_pending_object; |
| 62 | |
| 63 | struct breakpoint_object |
| 64 | { |
| 65 | PyObject_HEAD |
| 66 | |
| 67 | /* The breakpoint number according to gdb. */ |
| 68 | int number; |
| 69 | |
| 70 | /* The gdb breakpoint object, or NULL if the breakpoint has been |
| 71 | deleted. */ |
| 72 | struct breakpoint *bp; |
| 73 | }; |
| 74 | |
| 75 | #define BPPY_VALID_P(Num) \ |
| 76 | ((Num) >= 0 \ |
| 77 | && (Num) < bppy_slots \ |
| 78 | && bppy_breakpoints[Num] != NULL) |
| 79 | |
| 80 | #define BPPY_REQUIRE_VALID(Breakpoint) \ |
| 81 | do { \ |
| 82 | if (! BPPY_VALID_P ((Breakpoint)->number)) \ |
| 83 | return PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \ |
| 84 | (Breakpoint)->number); \ |
| 85 | } while (0) |
| 86 | |
| 87 | static PyMethodDef breakpoint_object_methods[] = |
| 88 | { |
| 89 | { "is_valid", bppy_is_valid, METH_NOARGS, |
| 90 | "Return true if this breakpoint is valid, false if not." }, |
| 91 | { "is_enabled", bppy_is_enabled, METH_NOARGS, |
| 92 | "Return true if this breakpoint is enabled, false if disabled." }, |
| 93 | { "is_silent", bppy_is_silent, METH_NOARGS, |
| 94 | "Return true if this breakpoint is silent, false if verbose." }, |
| 95 | |
| 96 | { "set_enabled", bppy_set_enabled, METH_O, |
| 97 | "Enable or disable this breakpoint" }, |
| 98 | { "set_silent", bppy_set_silent, METH_O, |
| 99 | "Make this breakpoint quiet or verbose" }, |
| 100 | |
| 101 | { "get_location", bppy_get_location, METH_NOARGS, |
| 102 | "Return the location of this breakpoint, as specified by the user"}, |
| 103 | { "get_condition", bppy_get_condition, METH_NOARGS, |
| 104 | "Return the condition of this breakpoint, as specified by the user.\n\ |
| 105 | Returns None if no condition set."}, |
| 106 | { "get_commands", bppy_get_commands, METH_NOARGS, |
| 107 | "Return the commands of this breakpoint, as specified by the user"}, |
| 108 | |
| 109 | { 0 } |
| 110 | }; |
| 111 | |
| 112 | static PyTypeObject breakpoint_object_type = |
| 113 | { |
| 114 | PyObject_HEAD_INIT (NULL) |
| 115 | 0, /*ob_size*/ |
| 116 | "gdb.Breakpoint", /*tp_name*/ |
| 117 | sizeof (breakpoint_object), /*tp_basicsize*/ |
| 118 | 0, /*tp_itemsize*/ |
| 119 | 0, /*tp_dealloc*/ |
| 120 | 0, /*tp_print*/ |
| 121 | 0, /*tp_getattr*/ |
| 122 | 0, /*tp_setattr*/ |
| 123 | 0, /*tp_compare*/ |
| 124 | 0, /*tp_repr*/ |
| 125 | 0, /*tp_as_number*/ |
| 126 | 0, /*tp_as_sequence*/ |
| 127 | 0, /*tp_as_mapping*/ |
| 128 | 0, /*tp_hash */ |
| 129 | 0, /*tp_call*/ |
| 130 | 0, /*tp_str*/ |
| 131 | 0, /*tp_getattro*/ |
| 132 | 0, /*tp_setattro*/ |
| 133 | 0, /*tp_as_buffer*/ |
| 134 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ |
| 135 | "GDB breakpoint object", /* tp_doc */ |
| 136 | 0, /* tp_traverse */ |
| 137 | 0, /* tp_clear */ |
| 138 | 0, /* tp_richcompare */ |
| 139 | 0, /* tp_weaklistoffset */ |
| 140 | 0, /* tp_iter */ |
| 141 | 0, /* tp_iternext */ |
| 142 | breakpoint_object_methods /* tp_methods */ |
| 143 | }; |
| 144 | |
| 145 | static PyObject * |
| 146 | bppy_is_valid (PyObject *self, PyObject *args) |
| 147 | { |
| 148 | if (((breakpoint_object *) self)->bp) |
| 149 | Py_RETURN_TRUE; |
| 150 | Py_RETURN_FALSE; |
| 151 | } |
| 152 | |
| 153 | static PyObject * |
| 154 | bppy_is_enabled (PyObject *self, PyObject *args) |
| 155 | { |
| 156 | if (! ((breakpoint_object *) self)->bp) |
| 157 | Py_RETURN_FALSE; |
| 158 | /* Not clear what we really want here. */ |
| 159 | if (((breakpoint_object *) self)->bp->enable_state == bp_enabled) |
| 160 | Py_RETURN_TRUE; |
| 161 | Py_RETURN_FALSE; |
| 162 | } |
| 163 | |
| 164 | static PyObject * |
| 165 | bppy_is_silent (PyObject *self, PyObject *args) |
| 166 | { |
| 167 | BPPY_REQUIRE_VALID ((breakpoint_object *) self); |
| 168 | if (((breakpoint_object *) self)->bp->silent) |
| 169 | Py_RETURN_TRUE; |
| 170 | Py_RETURN_FALSE; |
| 171 | } |
| 172 | |
| 173 | static PyObject * |
| 174 | bppy_set_enabled (PyObject *self, PyObject *newvalue) |
| 175 | { |
| 176 | breakpoint_object *self_bp = (breakpoint_object *) self; |
| 177 | |
| 178 | BPPY_REQUIRE_VALID (self_bp); |
| 179 | if (! PyBool_Check (newvalue)) |
| 180 | return PyErr_Format (PyExc_RuntimeError, "argument must be boolean"); |
| 181 | |
| 182 | if (newvalue == Py_True) |
| 183 | enable_breakpoint (self_bp->bp); |
| 184 | else |
| 185 | disable_breakpoint (self_bp->bp); |
| 186 | |
| 187 | Py_RETURN_NONE; |
| 188 | } |
| 189 | |
| 190 | static PyObject * |
| 191 | bppy_set_silent (PyObject *self, PyObject *newvalue) |
| 192 | { |
| 193 | breakpoint_object *self_bp = (breakpoint_object *) self; |
| 194 | |
| 195 | BPPY_REQUIRE_VALID (self_bp); |
| 196 | if (! PyBool_Check (newvalue)) |
| 197 | return PyErr_Format (PyExc_RuntimeError, "argument must be boolean"); |
| 198 | |
| 199 | self_bp->bp->silent = (newvalue == Py_True); |
| 200 | |
| 201 | Py_RETURN_NONE; |
| 202 | } |
| 203 | |
| 204 | static PyObject * |
| 205 | bppy_get_location (PyObject *self, PyObject *args) |
| 206 | { |
| 207 | char *str; |
| 208 | |
| 209 | BPPY_REQUIRE_VALID ((breakpoint_object *) self); |
| 210 | str = ((breakpoint_object *) self)->bp->addr_string; |
| 211 | /* FIXME: watchpoints? tracepoints? */ |
| 212 | if (! str) |
| 213 | str = ""; |
| 214 | return PyString_Decode (str, strlen (str), host_charset (), |
| 215 | NULL /* FIXME */); |
| 216 | } |
| 217 | |
| 218 | static PyObject * |
| 219 | bppy_get_condition (PyObject *self, PyObject *args) |
| 220 | { |
| 221 | char *str; |
| 222 | BPPY_REQUIRE_VALID ((breakpoint_object *) self); |
| 223 | |
| 224 | str = ((breakpoint_object *) self)->bp->cond_string; |
| 225 | if (! str) |
| 226 | Py_RETURN_NONE; |
| 227 | return PyString_Decode (str, strlen (str), host_charset (), |
| 228 | NULL /* FIXME */); |
| 229 | } |
| 230 | |
| 231 | static PyObject * |
| 232 | bppy_get_commands (PyObject *self, PyObject *args) |
| 233 | { |
| 234 | breakpoint_object *self_bp = (breakpoint_object *) self; |
| 235 | long length; |
| 236 | volatile struct gdb_exception except; |
| 237 | struct ui_file *string_file; |
| 238 | struct cleanup *chain; |
| 239 | PyObject *result; |
| 240 | char *cmdstr; |
| 241 | |
| 242 | BPPY_REQUIRE_VALID (self_bp); |
| 243 | |
| 244 | if (! self_bp->bp->commands) |
| 245 | Py_RETURN_NONE; |
| 246 | |
| 247 | string_file = mem_fileopen (); |
| 248 | chain = make_cleanup_ui_file_delete (string_file); |
| 249 | |
| 250 | TRY_CATCH (except, RETURN_MASK_ALL) |
| 251 | { |
| 252 | /* FIXME: this can fail. Maybe we need to be making a new |
| 253 | ui_out object here? */ |
| 254 | ui_out_redirect (uiout, string_file); |
| 255 | print_command_lines (uiout, self_bp->bp->commands, 0); |
| 256 | ui_out_redirect (uiout, NULL); |
| 257 | } |
| 258 | cmdstr = ui_file_xstrdup (string_file, &length); |
| 259 | GDB_PY_HANDLE_EXCEPTION (except); |
| 260 | |
| 261 | result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (), |
| 262 | NULL /* FIXME */); |
| 263 | do_cleanups (chain); |
| 264 | xfree (cmdstr); |
| 265 | return result; |
| 266 | } |
| 267 | |
| 268 | static PyObject * |
| 269 | bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs) |
| 270 | { |
| 271 | PyObject *result; |
| 272 | char *spec; |
| 273 | volatile struct gdb_exception except; |
| 274 | |
| 275 | /* FIXME: allow condition, thread, temporary, ... ? */ |
| 276 | if (! PyArg_ParseTuple (args, "s", &spec)) |
| 277 | return NULL; |
| 278 | result = subtype->tp_alloc (subtype, 0); |
| 279 | if (! result) |
| 280 | return NULL; |
| 281 | bppy_pending_object = (breakpoint_object *) result; |
| 282 | bppy_pending_object->number = -1; |
| 283 | bppy_pending_object->bp = NULL; |
| 284 | |
| 285 | TRY_CATCH (except, RETURN_MASK_ALL) |
| 286 | { |
| 287 | set_breakpoint (spec, NULL, 0, 0, -1, 0, AUTO_BOOLEAN_TRUE); |
| 288 | } |
| 289 | GDB_PY_HANDLE_EXCEPTION (except); |
| 290 | |
| 291 | BPPY_REQUIRE_VALID ((breakpoint_object *) result); |
| 292 | return result; |
| 293 | } |
| 294 | |
| 295 | |
| 296 | |
| 297 | /* Static function to return a tuple holding all breakpoints. */ |
| 298 | |
| 299 | PyObject * |
| 300 | gdbpy_get_breakpoints (PyObject *self, PyObject *args) |
| 301 | { |
| 302 | PyObject *result; |
| 303 | |
| 304 | if (bppy_live == 0) |
| 305 | Py_RETURN_NONE; |
| 306 | |
| 307 | result = PyTuple_New (bppy_live); |
| 308 | if (result) |
| 309 | { |
| 310 | int i, out = 0; |
| 311 | for (i = 0; out < bppy_live; ++i) |
| 312 | { |
| 313 | if (! bppy_breakpoints[i]) |
| 314 | continue; |
| 315 | Py_INCREF (bppy_breakpoints[i]); |
| 316 | PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]); |
| 317 | ++out; |
| 318 | } |
| 319 | } |
| 320 | return result; |
| 321 | } |
| 322 | |
| 323 | |
| 324 | |
| 325 | /* Event callback functions. */ |
| 326 | |
| 327 | void |
| 328 | gdbpy_breakpoint_created (int num) |
| 329 | { |
| 330 | breakpoint_object *newbp; |
| 331 | struct breakpoint *bp; |
| 332 | |
| 333 | if (num < 0) |
| 334 | return; |
| 335 | |
| 336 | for (bp = breakpoint_chain; bp; bp = bp->next) |
| 337 | if (bp->number == num) |
| 338 | break; |
| 339 | if (! bp) |
| 340 | return; |
| 341 | |
| 342 | if (num >= bppy_slots) |
| 343 | { |
| 344 | int old = bppy_slots; |
| 345 | bppy_slots = bppy_slots * 2 + 10; |
| 346 | bppy_breakpoints |
| 347 | = (breakpoint_object **) xrealloc (bppy_breakpoints, |
| 348 | (bppy_slots |
| 349 | * sizeof (breakpoint_object *))); |
| 350 | memset (&bppy_breakpoints[old], 0, |
| 351 | (bppy_slots - old) * sizeof (PyObject *)); |
| 352 | } |
| 353 | |
| 354 | ++bppy_live; |
| 355 | |
| 356 | if (bppy_pending_object) |
| 357 | { |
| 358 | newbp = bppy_pending_object; |
| 359 | bppy_pending_object = NULL; |
| 360 | } |
| 361 | else |
| 362 | newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); |
| 363 | if (newbp) |
| 364 | { |
| 365 | PyObject *hookfn; |
| 366 | |
| 367 | newbp->number = num; |
| 368 | newbp->bp = bp; |
| 369 | bppy_breakpoints[num] = newbp; |
| 370 | |
| 371 | hookfn = gdbpy_get_hook_function ("new_breakpoint"); |
| 372 | if (hookfn) |
| 373 | { |
| 374 | /* FIXME: refc? */ |
| 375 | PyObject_CallFunctionObjArgs (hookfn, newbp, NULL); |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | if (PyErr_Occurred ()) |
| 380 | { |
| 381 | /* FIXME -- what to do? */ |
| 382 | PyErr_Print (); |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | void |
| 387 | gdbpy_breakpoint_deleted (int num) |
| 388 | { |
| 389 | if (BPPY_VALID_P (num)) |
| 390 | { |
| 391 | bppy_breakpoints[num]->bp = NULL; |
| 392 | Py_DECREF (bppy_breakpoints[num]); |
| 393 | bppy_breakpoints[num] = NULL; |
| 394 | --bppy_live; |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | void |
| 399 | gdbpy_initialize_breakpoints (void) |
| 400 | { |
| 401 | breakpoint_object_type.tp_new = bppy_new; |
| 402 | if (PyType_Ready (&breakpoint_object_type) < 0) |
| 403 | return; |
| 404 | |
| 405 | Py_INCREF (&breakpoint_object_type); |
| 406 | PyModule_AddObject (gdb_module, "Breakpoint", |
| 407 | (PyObject *) &breakpoint_object_type); |
| 408 | } |
| toggle raw diff |
--- /dev/null
+++ b/gdb/python/breakpoint.c
@@ -0,0 +1,408 @@
+/* Python interface to breakpoints
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "breakpoint.h"
+#include "gdbcmd.h"
+
+
+/* From breakpoint.c. */
+extern struct breakpoint *breakpoint_chain;
+
+
+typedef struct breakpoint_object breakpoint_object;
+
+static PyObject *bppy_is_valid (PyObject *, PyObject *);
+static PyObject *bppy_is_enabled (PyObject *, PyObject *);
+static PyObject *bppy_is_silent (PyObject *, PyObject *);
+static PyObject *bppy_set_enabled (PyObject *, PyObject *);
+static PyObject *bppy_set_silent (PyObject *, PyObject *);
+static PyObject *bppy_get_location (PyObject *, PyObject *);
+static PyObject *bppy_get_condition (PyObject *, PyObject *);
+static PyObject *bppy_get_commands (PyObject *, PyObject *);
+
+
+/* A dynamically allocated vector of breakpoint objects. Each
+ breakpoint has a number. A breakpoint is valid if its slot in this
+ vector is non-null. When a breakpoint is deleted, we drop our
+ reference to it and zero its slot; this is how we let the Python
+ object have a lifetime which is independent from that of the gdb
+ breakpoint. */
+static breakpoint_object **bppy_breakpoints;
+
+/* Number of slots in bppy_breakpoints. */
+static int bppy_slots;
+
+/* Number of live breakpoints. */
+static int bppy_live;
+
+/* Variables used to pass information between the Breakpoint
+ constructor and the breakpoint-created hook function. */
+static breakpoint_object *bppy_pending_object;
+
+struct breakpoint_object
+{
+ PyObject_HEAD
+
+ /* The breakpoint number according to gdb. */
+ int number;
+
+ /* The gdb breakpoint object, or NULL if the breakpoint has been
+ deleted. */
+ struct breakpoint *bp;
+};
+
+#define BPPY_VALID_P(Num) \
+ ((Num) >= 0 \
+ && (Num) < bppy_slots \
+ && bppy_breakpoints[Num] != NULL)
+
+#define BPPY_REQUIRE_VALID(Breakpoint) \
+ do { \
+ if (! BPPY_VALID_P ((Breakpoint)->number)) \
+ return PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \
+ (Breakpoint)->number); \
+ } while (0)
+
+static PyMethodDef breakpoint_object_methods[] =
+{
+ { "is_valid", bppy_is_valid, METH_NOARGS,
+ "Return true if this breakpoint is valid, false if not." },
+ { "is_enabled", bppy_is_enabled, METH_NOARGS,
+ "Return true if this breakpoint is enabled, false if disabled." },
+ { "is_silent", bppy_is_silent, METH_NOARGS,
+ "Return true if this breakpoint is silent, false if verbose." },
+
+ { "set_enabled", bppy_set_enabled, METH_O,
+ "Enable or disable this breakpoint" },
+ { "set_silent", bppy_set_silent, METH_O,
+ "Make this breakpoint quiet or verbose" },
+
+ { "get_location", bppy_get_location, METH_NOARGS,
+ "Return the location of this breakpoint, as specified by the user"},
+ { "get_condition", bppy_get_condition, METH_NOARGS,
+ "Return the condition of this breakpoint, as specified by the user.\n\
+Returns None if no condition set."},
+ { "get_commands", bppy_get_commands, METH_NOARGS,
+ "Return the commands of this breakpoint, as specified by the user"},
+
+ { 0 }
+};
+
+static PyTypeObject breakpoint_object_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Breakpoint", /*tp_name*/
+ sizeof (breakpoint_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB breakpoint object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ breakpoint_object_methods /* tp_methods */
+};
+
+static PyObject *
+bppy_is_valid (PyObject *self, PyObject *args)
+{
+ if (((breakpoint_object *) self)->bp)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_is_enabled (PyObject *self, PyObject *args)
+{
+ if (! ((breakpoint_object *) self)->bp)
+ Py_RETURN_FALSE;
+ /* Not clear what we really want here. */
+ if (((breakpoint_object *) self)->bp->enable_state == bp_enabled)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_is_silent (PyObject *self, PyObject *args)
+{
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+ if (((breakpoint_object *) self)->bp->silent)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_set_enabled (PyObject *self, PyObject *newvalue)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+
+ BPPY_REQUIRE_VALID (self_bp);
+ if (! PyBool_Check (newvalue))
+ return PyErr_Format (PyExc_RuntimeError, "argument must be boolean");
+
+ if (newvalue == Py_True)
+ enable_breakpoint (self_bp->bp);
+ else
+ disable_breakpoint (self_bp->bp);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+bppy_set_silent (PyObject *self, PyObject *newvalue)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+
+ BPPY_REQUIRE_VALID (self_bp);
+ if (! PyBool_Check (newvalue))
+ return PyErr_Format (PyExc_RuntimeError, "argument must be boolean");
+
+ self_bp->bp->silent = (newvalue == Py_True);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+bppy_get_location (PyObject *self, PyObject *args)
+{
+ char *str;
+
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+ str = ((breakpoint_object *) self)->bp->addr_string;
+ /* FIXME: watchpoints? tracepoints? */
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (),
+ NULL /* FIXME */);
+}
+
+static PyObject *
+bppy_get_condition (PyObject *self, PyObject *args)
+{
+ char *str;
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+
+ str = ((breakpoint_object *) self)->bp->cond_string;
+ if (! str)
+ Py_RETURN_NONE;
+ return PyString_Decode (str, strlen (str), host_charset (),
+ NULL /* FIXME */);
+}
+
+static PyObject *
+bppy_get_commands (PyObject *self, PyObject *args)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+ long length;
+ volatile struct gdb_exception except;
+ struct ui_file *string_file;
+ struct cleanup *chain;
+ PyObject *result;
+ char *cmdstr;
+
+ BPPY_REQUIRE_VALID (self_bp);
+
+ if (! self_bp->bp->commands)
+ Py_RETURN_NONE;
+
+ string_file = mem_fileopen ();
+ chain = make_cleanup_ui_file_delete (string_file);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* FIXME: this can fail. Maybe we need to be making a new
+ ui_out object here? */
+ ui_out_redirect (uiout, string_file);
+ print_command_lines (uiout, self_bp->bp->commands, 0);
+ ui_out_redirect (uiout, NULL);
+ }
+ cmdstr = ui_file_xstrdup (string_file, &length);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (),
+ NULL /* FIXME */);
+ do_cleanups (chain);
+ xfree (cmdstr);
+ return result;
+}
+
+static PyObject *
+bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+{
+ PyObject *result;
+ char *spec;
+ volatile struct gdb_exception except;
+
+ /* FIXME: allow condition, thread, temporary, ... ? */
+ if (! PyArg_ParseTuple (args, "s", &spec))
+ return NULL;
+ result = subtype->tp_alloc (subtype, 0);
+ if (! result)
+ return NULL;
+ bppy_pending_object = (breakpoint_object *) result;
+ bppy_pending_object->number = -1;
+ bppy_pending_object->bp = NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ set_breakpoint (spec, NULL, 0, 0, -1, 0, AUTO_BOOLEAN_TRUE);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ BPPY_REQUIRE_VALID ((breakpoint_object *) result);
+ return result;
+}
+
+
+
+/* Static function to return a tuple holding all breakpoints. */
+
+PyObject *
+gdbpy_get_breakpoints (PyObject *self, PyObject *args)
+{
+ PyObject *result;
+
+ if (bppy_live == 0)
+ Py_RETURN_NONE;
+
+ result = PyTuple_New (bppy_live);
+ if (result)
+ {
+ int i, out = 0;
+ for (i = 0; out < bppy_live; ++i)
+ {
+ if (! bppy_breakpoints[i])
+ continue;
+ Py_INCREF (bppy_breakpoints[i]);
+ PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]);
+ ++out;
+ }
+ }
+ return result;
+}
+
+
+
+/* Event callback functions. */
+
+void
+gdbpy_breakpoint_created (int num)
+{
+ breakpoint_object *newbp;
+ struct breakpoint *bp;
+
+ if (num < 0)
+ return;
+
+ for (bp = breakpoint_chain; bp; bp = bp->next)
+ if (bp->number == num)
+ break;
+ if (! bp)
+ return;
+
+ if (num >= bppy_slots)
+ {
+ int old = bppy_slots;
+ bppy_slots = bppy_slots * 2 + 10;
+ bppy_breakpoints
+ = (breakpoint_object **) xrealloc (bppy_breakpoints,
+ (bppy_slots
+ * sizeof (breakpoint_object *)));
+ memset (&bppy_breakpoints[old], 0,
+ (bppy_slots - old) * sizeof (PyObject *));
+ }
+
+ ++bppy_live;
+
+ if (bppy_pending_object)
+ {
+ newbp = bppy_pending_object;
+ bppy_pending_object = NULL;
+ }
+ else
+ newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
+ if (newbp)
+ {
+ PyObject *hookfn;
+
+ newbp->number = num;
+ newbp->bp = bp;
+ bppy_breakpoints[num] = newbp;
+
+ hookfn = gdbpy_get_hook_function ("new_breakpoint");
+ if (hookfn)
+ {
+ /* FIXME: refc? */
+ PyObject_CallFunctionObjArgs (hookfn, newbp, NULL);
+ }
+ }
+
+ if (PyErr_Occurred ())
+ {
+ /* FIXME -- what to do? */
+ PyErr_Print ();
+ }
+}
+
+void
+gdbpy_breakpoint_deleted (int num)
+{
+ if (BPPY_VALID_P (num))
+ {
+ bppy_breakpoints[num]->bp = NULL;
+ Py_DECREF (bppy_breakpoints[num]);
+ bppy_breakpoints[num] = NULL;
+ --bppy_live;
+ }
+}
+
+void
+gdbpy_initialize_breakpoints (void)
+{
+ breakpoint_object_type.tp_new = bppy_new;
+ if (PyType_Ready (&breakpoint_object_type) < 0)
+ return;
+
+ Py_INCREF (&breakpoint_object_type);
+ PyModule_AddObject (gdb_module, "Breakpoint",
+ (PyObject *) &breakpoint_object_type);
+} |