]> Git Repo - binutils.git/blob - gdb/python/py-frame.c
2011-10-27 Phil Muldoon <[email protected]>
[binutils.git] / gdb / python / py-frame.c
1 /* Python interface to stack frames
2
3    Copyright (C) 2008, 2009, 2010, 2011 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 "charset.h"
22 #include "block.h"
23 #include "frame.h"
24 #include "exceptions.h"
25 #include "symtab.h"
26 #include "stack.h"
27 #include "value.h"
28 #include "python-internal.h"
29 #include "symfile.h"
30 #include "objfiles.h"
31
32 typedef struct {
33   PyObject_HEAD
34   struct frame_id frame_id;
35   struct gdbarch *gdbarch;
36
37   /* Marks that the FRAME_ID member actually holds the ID of the frame next
38      to this, and not this frames' ID itself.  This is a hack to permit Python
39      frame objects which represent invalid frames (i.e., the last frame_info
40      in a corrupt stack).  The problem arises from the fact that this code
41      relies on FRAME_ID to uniquely identify a frame, which is not always true
42      for the last "frame" in a corrupt stack (it can have a null ID, or the same
43      ID as the  previous frame).  Whenever get_prev_frame returns NULL, we
44      record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1.  */
45   int frame_id_is_next;
46 } frame_object;
47
48 /* Require a valid frame.  This must be called inside a TRY_CATCH, or
49    another context in which a gdb exception is allowed.  */
50 #define FRAPY_REQUIRE_VALID(frame_obj, frame)           \
51     do {                                                \
52       frame = frame_object_to_frame_info (frame_obj);   \
53       if (frame == NULL)                                \
54         error (_("Frame is invalid."));                 \
55     } while (0)
56
57 static PyTypeObject frame_object_type;
58
59 /* Returns the frame_info object corresponding to the given Python Frame
60    object.  If the frame doesn't exist anymore (the frame id doesn't
61    correspond to any frame in the inferior), returns NULL.  */
62
63 static struct frame_info *
64 frame_object_to_frame_info (frame_object *frame_obj)
65 {
66   struct frame_info *frame;
67
68   frame = frame_find_by_id (frame_obj->frame_id);
69   if (frame == NULL)
70     return NULL;
71
72   if (frame_obj->frame_id_is_next)
73     frame = get_prev_frame (frame);
74
75   return frame;
76 }
77
78 /* Called by the Python interpreter to obtain string representation
79    of the object.  */
80
81 static PyObject *
82 frapy_str (PyObject *self)
83 {
84   char *s;
85   PyObject *result;
86   struct ui_file *strfile;
87
88   strfile = mem_fileopen ();
89   fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
90   s = ui_file_xstrdup (strfile, NULL);
91   result = PyString_FromString (s);
92   xfree (s);
93
94   return result;
95 }
96
97 /* Implementation of gdb.Frame.is_valid (self) -> Boolean.
98    Returns True if the frame corresponding to the frame_id of this
99    object still exists in the inferior.  */
100
101 static PyObject *
102 frapy_is_valid (PyObject *self, PyObject *args)
103 {
104   struct frame_info *frame = NULL;
105   volatile struct gdb_exception except;
106
107   TRY_CATCH (except, RETURN_MASK_ALL)
108     {
109       frame = frame_object_to_frame_info ((frame_object *) self);
110     }
111   GDB_PY_HANDLE_EXCEPTION (except);
112
113   if (frame == NULL)
114     Py_RETURN_FALSE;
115
116   Py_RETURN_TRUE;
117 }
118
119 /* Implementation of gdb.Frame.name (self) -> String.
120    Returns the name of the function corresponding to this frame.  */
121
122 static PyObject *
123 frapy_name (PyObject *self, PyObject *args)
124 {
125   struct frame_info *frame;
126   char *name;
127   enum language lang;
128   PyObject *result;
129   volatile struct gdb_exception except;
130
131   TRY_CATCH (except, RETURN_MASK_ALL)
132     {
133       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
134
135       find_frame_funname (frame, &name, &lang, NULL);
136     }
137   GDB_PY_HANDLE_EXCEPTION (except);
138
139   if (name)
140     result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
141   else
142     {
143       result = Py_None;
144       Py_INCREF (Py_None);
145     }
146
147   return result;
148 }
149
150 /* Implementation of gdb.Frame.type (self) -> Integer.
151    Returns the frame type, namely one of the gdb.*_FRAME constants.  */
152
153 static PyObject *
154 frapy_type (PyObject *self, PyObject *args)
155 {
156   struct frame_info *frame;
157   enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning.  */
158   volatile struct gdb_exception except;
159
160   TRY_CATCH (except, RETURN_MASK_ALL)
161     {
162       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
163
164       type = get_frame_type (frame);
165     }
166   GDB_PY_HANDLE_EXCEPTION (except);
167
168   return PyInt_FromLong (type);
169 }
170
171 /* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
172    Returns one of the gdb.FRAME_UNWIND_* constants.  */
173
174 static PyObject *
175 frapy_unwind_stop_reason (PyObject *self, PyObject *args)
176 {
177   struct frame_info *frame = NULL;    /* Initialize to appease gcc warning.  */
178   volatile struct gdb_exception except;
179   enum unwind_stop_reason stop_reason;
180
181   TRY_CATCH (except, RETURN_MASK_ALL)
182     {
183       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
184     }
185   GDB_PY_HANDLE_EXCEPTION (except);
186
187   stop_reason = get_frame_unwind_stop_reason (frame);
188
189   return PyInt_FromLong (stop_reason);
190 }
191
192 /* Implementation of gdb.Frame.pc (self) -> Long.
193    Returns the frame's resume address.  */
194
195 static PyObject *
196 frapy_pc (PyObject *self, PyObject *args)
197 {
198   CORE_ADDR pc = 0;           /* Initialize to appease gcc warning.  */
199   struct frame_info *frame;
200   volatile struct gdb_exception except;
201
202   TRY_CATCH (except, RETURN_MASK_ALL)
203     {
204       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
205
206       pc = get_frame_pc (frame);
207     }
208   GDB_PY_HANDLE_EXCEPTION (except);
209
210   return gdb_py_long_from_ulongest (pc);
211 }
212
213 /* Implementation of gdb.Frame.block (self) -> gdb.Block.
214    Returns the frame's code block.  */
215
216 static PyObject *
217 frapy_block (PyObject *self, PyObject *args)
218 {
219   struct frame_info *frame;
220   struct block *block = NULL, *fn_block;
221   volatile struct gdb_exception except;
222
223   TRY_CATCH (except, RETURN_MASK_ALL)
224     {
225       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
226       block = get_frame_block (frame, NULL);
227     }
228   GDB_PY_HANDLE_EXCEPTION (except);
229
230   for (fn_block = block;
231        fn_block != NULL && BLOCK_FUNCTION (fn_block) == NULL;
232        fn_block = BLOCK_SUPERBLOCK (fn_block))
233     ;
234
235   if (block == NULL || fn_block == NULL || BLOCK_FUNCTION (fn_block) == NULL)
236     {
237       PyErr_SetString (PyExc_RuntimeError,
238                        _("Cannot locate object file for block."));
239       return NULL;
240     }
241
242   if (block)
243     {
244       struct symtab *symt;
245
246       symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block));
247       return block_to_block_object (block, symt->objfile);
248     }
249
250   Py_RETURN_NONE;
251 }
252
253
254 /* Implementation of gdb.Frame.function (self) -> gdb.Symbol.
255    Returns the symbol for the function corresponding to this frame.  */
256
257 static PyObject *
258 frapy_function (PyObject *self, PyObject *args)
259 {
260   struct symbol *sym = NULL;
261   struct frame_info *frame;
262   volatile struct gdb_exception except;
263
264   TRY_CATCH (except, RETURN_MASK_ALL)
265     {
266       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
267
268       sym = find_pc_function (get_frame_address_in_block (frame));
269     }
270   GDB_PY_HANDLE_EXCEPTION (except);
271
272   if (sym)
273     return symbol_to_symbol_object (sym);
274
275   Py_RETURN_NONE;
276 }
277
278 /* Convert a frame_info struct to a Python Frame object.
279    Sets a Python exception and returns NULL on error.  */
280
281 PyObject *
282 frame_info_to_frame_object (struct frame_info *frame)
283 {
284   frame_object *frame_obj;
285   volatile struct gdb_exception except;
286
287   frame_obj = PyObject_New (frame_object, &frame_object_type);
288   if (frame_obj == NULL)
289     {
290       PyErr_SetString (PyExc_MemoryError, 
291                        _("Could not allocate frame object."));
292       return NULL;
293     }
294
295   TRY_CATCH (except, RETURN_MASK_ALL)
296     {
297
298       /* Try to get the previous frame, to determine if this is the last frame
299          in a corrupt stack.  If so, we need to store the frame_id of the next
300          frame and not of this one (which is possibly invalid).  */
301       if (get_prev_frame (frame) == NULL
302           && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
303           && get_next_frame (frame) != NULL)
304         {
305           frame_obj->frame_id = get_frame_id (get_next_frame (frame));
306           frame_obj->frame_id_is_next = 1;
307         }
308       else
309         {
310           frame_obj->frame_id = get_frame_id (frame);
311           frame_obj->frame_id_is_next = 0;
312         }
313       frame_obj->gdbarch = get_frame_arch (frame);
314     }
315   GDB_PY_HANDLE_EXCEPTION (except);
316
317   return (PyObject *) frame_obj;
318 }
319
320 /* Implementation of gdb.Frame.older (self) -> gdb.Frame.
321    Returns the frame immediately older (outer) to this frame, or None if
322    there isn't one.  */
323
324 static PyObject *
325 frapy_older (PyObject *self, PyObject *args)
326 {
327   struct frame_info *frame, *prev;
328   volatile struct gdb_exception except;
329   PyObject *prev_obj = NULL;   /* Initialize to appease gcc warning.  */
330
331   TRY_CATCH (except, RETURN_MASK_ALL)
332     {
333       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
334
335       prev = get_prev_frame (frame);
336       if (prev)
337         prev_obj = (PyObject *) frame_info_to_frame_object (prev);
338       else
339         {
340           Py_INCREF (Py_None);
341           prev_obj = Py_None;
342         }
343     }
344   GDB_PY_HANDLE_EXCEPTION (except);
345
346   return prev_obj;
347 }
348
349 /* Implementation of gdb.Frame.newer (self) -> gdb.Frame.
350    Returns the frame immediately newer (inner) to this frame, or None if
351    there isn't one.  */
352
353 static PyObject *
354 frapy_newer (PyObject *self, PyObject *args)
355 {
356   struct frame_info *frame, *next;
357   volatile struct gdb_exception except;
358   PyObject *next_obj = NULL;   /* Initialize to appease gcc warning.  */
359
360   TRY_CATCH (except, RETURN_MASK_ALL)
361     {
362       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
363
364       next = get_next_frame (frame);
365       if (next)
366         next_obj = (PyObject *) frame_info_to_frame_object (next);
367       else
368         {
369           Py_INCREF (Py_None);
370           next_obj = Py_None;
371         }
372     }
373   GDB_PY_HANDLE_EXCEPTION (except);
374
375   return next_obj;
376 }
377
378 /* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line.
379    Returns the frame's symtab and line.  */
380
381 static PyObject *
382 frapy_find_sal (PyObject *self, PyObject *args)
383 {
384   struct frame_info *frame;
385   struct symtab_and_line sal;
386   volatile struct gdb_exception except;
387   PyObject *sal_obj = NULL;   /* Initialize to appease gcc warning.  */
388
389   TRY_CATCH (except, RETURN_MASK_ALL)
390     {
391       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
392
393       find_frame_sal (frame, &sal);
394       sal_obj = symtab_and_line_to_sal_object (sal);
395     }
396   GDB_PY_HANDLE_EXCEPTION (except);
397
398   return sal_obj;
399 }
400
401 /* Implementation of gdb.Frame.read_var_value (self, variable,
402    [block]) -> gdb.Value.  If the optional block argument is provided
403    start the search from that block, otherwise search from the frame's
404    current block (determined by examining the resume address of the
405    frame).  The variable argument must be a string or an instance of a
406    gdb.Symbol.  The block argument must be an instance of gdb.Block.  Returns
407    NULL on error, with a python exception set.  */
408 static PyObject *
409 frapy_read_var (PyObject *self, PyObject *args)
410 {
411   struct frame_info *frame;
412   PyObject *sym_obj, *block_obj = NULL;
413   struct symbol *var = NULL;    /* gcc-4.3.2 false warning.  */
414   struct value *val = NULL;
415   volatile struct gdb_exception except;
416
417   if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj))
418     return NULL;
419
420   if (PyObject_TypeCheck (sym_obj, &symbol_object_type))
421     var = symbol_object_to_symbol (sym_obj);
422   else if (gdbpy_is_string (sym_obj))
423     {
424       char *var_name;
425       const struct block *block = NULL;
426       struct cleanup *cleanup;
427       volatile struct gdb_exception except;
428
429       var_name = python_string_to_target_string (sym_obj);
430       if (!var_name)
431         return NULL;
432       cleanup = make_cleanup (xfree, var_name);
433
434       if (block_obj)
435         {
436           block = block_object_to_block (block_obj);
437           if (!block)
438             {
439               PyErr_SetString (PyExc_RuntimeError,
440                                _("Second argument must be block."));
441               return NULL;
442             }
443         }
444
445       TRY_CATCH (except, RETURN_MASK_ALL)
446         {
447           FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
448
449           if (!block)
450             block = get_frame_block (frame, NULL);
451           var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
452         }
453       GDB_PY_HANDLE_EXCEPTION (except);
454
455       if (!var)
456         {
457           PyErr_Format (PyExc_ValueError,
458                         _("Variable '%s' not found."), var_name);
459           do_cleanups (cleanup);
460
461           return NULL;
462         }
463
464       do_cleanups (cleanup);
465     }
466   else
467     {
468       PyErr_SetString (PyExc_TypeError,
469                        _("Argument must be a symbol or string."));
470       return NULL;
471     }
472
473   TRY_CATCH (except, RETURN_MASK_ALL)
474     {
475       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
476
477       val = read_var_value (var, frame);
478     }
479   GDB_PY_HANDLE_EXCEPTION (except);
480
481   return value_to_value_object (val);
482 }
483
484 /* Select this frame.  */
485
486 static PyObject *
487 frapy_select (PyObject *self, PyObject *args)
488 {
489   struct frame_info *fi;
490   frame_object *frame = (frame_object *) self;
491   volatile struct gdb_exception except;
492
493   TRY_CATCH (except, RETURN_MASK_ALL)
494     {
495       FRAPY_REQUIRE_VALID (frame, fi);
496
497       select_frame (fi);
498     }
499   GDB_PY_HANDLE_EXCEPTION (except);
500
501   Py_RETURN_NONE;
502 }
503
504 /* Implementation of gdb.newest_frame () -> gdb.Frame.
505    Returns the newest frame object.  */
506
507 PyObject *
508 gdbpy_newest_frame (PyObject *self, PyObject *args)
509 {
510   struct frame_info *frame;
511   PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
512   volatile struct gdb_exception except;
513
514   TRY_CATCH (except, RETURN_MASK_ALL)
515     {
516       frame = get_current_frame ();
517       frame_obj = frame_info_to_frame_object (frame);
518     }
519   GDB_PY_HANDLE_EXCEPTION (except);
520
521   return frame_obj;
522 }
523
524 /* Implementation of gdb.selected_frame () -> gdb.Frame.
525    Returns the selected frame object.  */
526
527 PyObject *
528 gdbpy_selected_frame (PyObject *self, PyObject *args)
529 {
530   struct frame_info *frame;
531   PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
532   volatile struct gdb_exception except;
533
534   TRY_CATCH (except, RETURN_MASK_ALL)
535     {
536       frame = get_selected_frame ("No frame is currently selected.");
537       frame_obj = frame_info_to_frame_object (frame);
538     }
539   GDB_PY_HANDLE_EXCEPTION (except);
540
541   return frame_obj;
542 }
543
544 /* Implementation of gdb.stop_reason_string (Integer) -> String.
545    Return a string explaining the unwind stop reason.  */
546
547 PyObject *
548 gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
549 {
550   int reason;
551   const char *str;
552
553   if (!PyArg_ParseTuple (args, "i", &reason))
554     return NULL;
555
556   if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
557     {
558       PyErr_SetString (PyExc_ValueError, 
559                        _("Invalid frame stop reason."));
560       return NULL;
561     }
562
563   str = frame_stop_reason_string (reason);
564   return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
565 }
566
567 /* Implements the equality comparison for Frame objects.
568    All other comparison operators will throw a TypeError Python exception,
569    as they aren't valid for frames.  */
570
571 static PyObject *
572 frapy_richcompare (PyObject *self, PyObject *other, int op)
573 {
574   int result;
575
576   if (!PyObject_TypeCheck (other, &frame_object_type)
577       || (op != Py_EQ && op != Py_NE))
578     {
579       Py_INCREF (Py_NotImplemented);
580       return Py_NotImplemented;
581     }
582
583   if (frame_id_eq (((frame_object *) self)->frame_id,
584                    ((frame_object *) other)->frame_id))
585     result = Py_EQ;
586   else
587     result = Py_NE;
588
589   if (op == result)
590     Py_RETURN_TRUE;
591   Py_RETURN_FALSE;
592 }
593
594 /* Sets up the Frame API in the gdb module.  */
595
596 void
597 gdbpy_initialize_frames (void)
598 {
599   frame_object_type.tp_new = PyType_GenericNew;
600   if (PyType_Ready (&frame_object_type) < 0)
601     return;
602
603   /* Note: These would probably be best exposed as class attributes of
604      Frame, but I don't know how to do it except by messing with the
605      type's dictionary.  That seems too messy.  */
606   PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
607   PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
608   PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME);
609   PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME);
610   PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
611   PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
612   PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
613   PyModule_AddIntConstant (gdb_module,
614                            "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
615   PyModule_AddIntConstant (gdb_module,
616                            "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
617   PyModule_AddIntConstant (gdb_module,
618                            "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
619   PyModule_AddIntConstant (gdb_module,
620                            "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
621   PyModule_AddIntConstant (gdb_module,
622                            "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
623   PyModule_AddIntConstant (gdb_module,
624                            "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
625
626   Py_INCREF (&frame_object_type);
627   PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
628 }
629
630 \f
631
632 static PyMethodDef frame_object_methods[] = {
633   { "is_valid", frapy_is_valid, METH_NOARGS,
634     "is_valid () -> Boolean.\n\
635 Return true if this frame is valid, false if not." },
636   { "name", frapy_name, METH_NOARGS,
637     "name () -> String.\n\
638 Return the function name of the frame, or None if it can't be determined." },
639   { "type", frapy_type, METH_NOARGS,
640     "type () -> Integer.\n\
641 Return the type of the frame." },
642   { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
643     "unwind_stop_reason () -> Integer.\n\
644 Return the reason why it's not possible to find frames older than this." },
645   { "pc", frapy_pc, METH_NOARGS,
646     "pc () -> Long.\n\
647 Return the frame's resume address." },
648   { "block", frapy_block, METH_NOARGS,
649     "block () -> gdb.Block.\n\
650 Return the frame's code block." },
651   { "function", frapy_function, METH_NOARGS,
652     "function () -> gdb.Symbol.\n\
653 Returns the symbol for the function corresponding to this frame." },
654   { "older", frapy_older, METH_NOARGS,
655     "older () -> gdb.Frame.\n\
656 Return the frame that called this frame." },
657   { "newer", frapy_newer, METH_NOARGS,
658     "newer () -> gdb.Frame.\n\
659 Return the frame called by this frame." },
660   { "find_sal", frapy_find_sal, METH_NOARGS,
661     "find_sal () -> gdb.Symtab_and_line.\n\
662 Return the frame's symtab and line." },
663   { "read_var", frapy_read_var, METH_VARARGS,
664     "read_var (variable) -> gdb.Value.\n\
665 Return the value of the variable in this frame." },
666   { "select", frapy_select, METH_NOARGS,
667     "Select this frame as the user's current frame." },
668   {NULL}  /* Sentinel */
669 };
670
671 static PyTypeObject frame_object_type = {
672   PyObject_HEAD_INIT (NULL)
673   0,                              /* ob_size */
674   "gdb.Frame",                    /* tp_name */
675   sizeof (frame_object),          /* tp_basicsize */
676   0,                              /* tp_itemsize */
677   0,                              /* tp_dealloc */
678   0,                              /* tp_print */
679   0,                              /* tp_getattr */
680   0,                              /* tp_setattr */
681   0,                              /* tp_compare */
682   0,                              /* tp_repr */
683   0,                              /* tp_as_number */
684   0,                              /* tp_as_sequence */
685   0,                              /* tp_as_mapping */
686   0,                              /* tp_hash  */
687   0,                              /* tp_call */
688   frapy_str,                      /* tp_str */
689   0,                              /* tp_getattro */
690   0,                              /* tp_setattro */
691   0,                              /* tp_as_buffer */
692   Py_TPFLAGS_DEFAULT,             /* tp_flags */
693   "GDB frame object",             /* tp_doc */
694   0,                              /* tp_traverse */
695   0,                              /* tp_clear */
696   frapy_richcompare,              /* tp_richcompare */
697   0,                              /* tp_weaklistoffset */
698   0,                              /* tp_iter */
699   0,                              /* tp_iternext */
700   frame_object_methods,           /* tp_methods */
701   0,                              /* tp_members */
702   0,                              /* tp_getset */
703   0,                              /* tp_base */
704   0,                              /* tp_dict */
705   0,                              /* tp_descr_get */
706   0,                              /* tp_descr_set */
707   0,                              /* tp_dictoffset */
708   0,                              /* tp_init */
709   0,                              /* tp_alloc */
710 };
This page took 0.066708 seconds and 4 git commands to generate.