]> Git Repo - binutils.git/blob - gdb/python/py-frame.c
398ce84bcd113b0dc566ddef221c8f8e3e191a6a
[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;
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       const 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   return value_to_value_object (val);
471 }
472
473 /* Select this frame.  */
474
475 static PyObject *
476 frapy_select (PyObject *self, PyObject *args)
477 {
478   struct frame_info *fi;
479   frame_object *frame = (frame_object *) self;
480   volatile struct gdb_exception except;
481
482   TRY_CATCH (except, RETURN_MASK_ALL)
483     {
484       FRAPY_REQUIRE_VALID (frame, fi);
485
486       select_frame (fi);
487     }
488   GDB_PY_HANDLE_EXCEPTION (except);
489
490   Py_RETURN_NONE;
491 }
492
493 /* Implementation of gdb.newest_frame () -> gdb.Frame.
494    Returns the newest frame object.  */
495
496 PyObject *
497 gdbpy_newest_frame (PyObject *self, PyObject *args)
498 {
499   struct frame_info *frame;
500   PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
501   volatile struct gdb_exception except;
502
503   TRY_CATCH (except, RETURN_MASK_ALL)
504     {
505       frame = get_current_frame ();
506       frame_obj = frame_info_to_frame_object (frame);
507     }
508   GDB_PY_HANDLE_EXCEPTION (except);
509
510   return frame_obj;
511 }
512
513 /* Implementation of gdb.selected_frame () -> gdb.Frame.
514    Returns the selected frame object.  */
515
516 PyObject *
517 gdbpy_selected_frame (PyObject *self, PyObject *args)
518 {
519   struct frame_info *frame;
520   PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
521   volatile struct gdb_exception except;
522
523   TRY_CATCH (except, RETURN_MASK_ALL)
524     {
525       frame = get_selected_frame ("No frame is currently selected.");
526       frame_obj = frame_info_to_frame_object (frame);
527     }
528   GDB_PY_HANDLE_EXCEPTION (except);
529
530   return frame_obj;
531 }
532
533 /* Implementation of gdb.stop_reason_string (Integer) -> String.
534    Return a string explaining the unwind stop reason.  */
535
536 PyObject *
537 gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
538 {
539   int reason;
540   const char *str;
541
542   if (!PyArg_ParseTuple (args, "i", &reason))
543     return NULL;
544
545   if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
546     {
547       PyErr_SetString (PyExc_ValueError, 
548                        _("Invalid frame stop reason."));
549       return NULL;
550     }
551
552   str = frame_stop_reason_string (reason);
553   return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
554 }
555
556 /* Implements the equality comparison for Frame objects.
557    All other comparison operators will throw a TypeError Python exception,
558    as they aren't valid for frames.  */
559
560 static PyObject *
561 frapy_richcompare (PyObject *self, PyObject *other, int op)
562 {
563   int result;
564
565   if (!PyObject_TypeCheck (other, &frame_object_type)
566       || (op != Py_EQ && op != Py_NE))
567     {
568       Py_INCREF (Py_NotImplemented);
569       return Py_NotImplemented;
570     }
571
572   if (frame_id_eq (((frame_object *) self)->frame_id,
573                    ((frame_object *) other)->frame_id))
574     result = Py_EQ;
575   else
576     result = Py_NE;
577
578   if (op == result)
579     Py_RETURN_TRUE;
580   Py_RETURN_FALSE;
581 }
582
583 /* Sets up the Frame API in the gdb module.  */
584
585 void
586 gdbpy_initialize_frames (void)
587 {
588   frame_object_type.tp_new = PyType_GenericNew;
589   if (PyType_Ready (&frame_object_type) < 0)
590     return;
591
592   /* Note: These would probably be best exposed as class attributes of
593      Frame, but I don't know how to do it except by messing with the
594      type's dictionary.  That seems too messy.  */
595   PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
596   PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
597   PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME);
598   PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME);
599   PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
600   PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
601   PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
602   PyModule_AddIntConstant (gdb_module,
603                            "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
604   PyModule_AddIntConstant (gdb_module,
605                            "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
606   PyModule_AddIntConstant (gdb_module,
607                            "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
608   PyModule_AddIntConstant (gdb_module,
609                            "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
610   PyModule_AddIntConstant (gdb_module,
611                            "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
612   PyModule_AddIntConstant (gdb_module,
613                            "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
614
615   Py_INCREF (&frame_object_type);
616   PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
617 }
618
619 \f
620
621 static PyMethodDef frame_object_methods[] = {
622   { "is_valid", frapy_is_valid, METH_NOARGS,
623     "is_valid () -> Boolean.\n\
624 Return true if this frame is valid, false if not." },
625   { "name", frapy_name, METH_NOARGS,
626     "name () -> String.\n\
627 Return the function name of the frame, or None if it can't be determined." },
628   { "type", frapy_type, METH_NOARGS,
629     "type () -> Integer.\n\
630 Return the type of the frame." },
631   { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
632     "unwind_stop_reason () -> Integer.\n\
633 Return the reason why it's not possible to find frames older than this." },
634   { "pc", frapy_pc, METH_NOARGS,
635     "pc () -> Long.\n\
636 Return the frame's resume address." },
637   { "block", frapy_block, METH_NOARGS,
638     "block () -> gdb.Block.\n\
639 Return the frame's code block." },
640   { "function", frapy_function, METH_NOARGS,
641     "function () -> gdb.Symbol.\n\
642 Returns the symbol for the function corresponding to this frame." },
643   { "older", frapy_older, METH_NOARGS,
644     "older () -> gdb.Frame.\n\
645 Return the frame that called this frame." },
646   { "newer", frapy_newer, METH_NOARGS,
647     "newer () -> gdb.Frame.\n\
648 Return the frame called by this frame." },
649   { "find_sal", frapy_find_sal, METH_NOARGS,
650     "find_sal () -> gdb.Symtab_and_line.\n\
651 Return the frame's symtab and line." },
652   { "read_var", frapy_read_var, METH_VARARGS,
653     "read_var (variable) -> gdb.Value.\n\
654 Return the value of the variable in this frame." },
655   { "select", frapy_select, METH_NOARGS,
656     "Select this frame as the user's current frame." },
657   {NULL}  /* Sentinel */
658 };
659
660 static PyTypeObject frame_object_type = {
661   PyObject_HEAD_INIT (NULL)
662   0,                              /* ob_size */
663   "gdb.Frame",                    /* tp_name */
664   sizeof (frame_object),          /* tp_basicsize */
665   0,                              /* tp_itemsize */
666   0,                              /* tp_dealloc */
667   0,                              /* tp_print */
668   0,                              /* tp_getattr */
669   0,                              /* tp_setattr */
670   0,                              /* tp_compare */
671   0,                              /* tp_repr */
672   0,                              /* tp_as_number */
673   0,                              /* tp_as_sequence */
674   0,                              /* tp_as_mapping */
675   0,                              /* tp_hash  */
676   0,                              /* tp_call */
677   frapy_str,                      /* tp_str */
678   0,                              /* tp_getattro */
679   0,                              /* tp_setattro */
680   0,                              /* tp_as_buffer */
681   Py_TPFLAGS_DEFAULT,             /* tp_flags */
682   "GDB frame object",             /* tp_doc */
683   0,                              /* tp_traverse */
684   0,                              /* tp_clear */
685   frapy_richcompare,              /* tp_richcompare */
686   0,                              /* tp_weaklistoffset */
687   0,                              /* tp_iter */
688   0,                              /* tp_iternext */
689   frame_object_methods,           /* tp_methods */
690   0,                              /* tp_members */
691   0,                              /* tp_getset */
692   0,                              /* tp_base */
693   0,                              /* tp_dict */
694   0,                              /* tp_descr_get */
695   0,                              /* tp_descr_set */
696   0,                              /* tp_dictoffset */
697   0,                              /* tp_init */
698   0,                              /* tp_alloc */
699 };
This page took 0.05461 seconds and 2 git commands to generate.