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