OSDN Git Service

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