1 /* GDB parameters implemented in Python 2 3 Copyright (C) 2008-2013 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 21 #include "defs.h" 22 #include "value.h" 23 #include "exceptions.h" 24 #include "python-internal.h" 25 #include "charset.h" 26 #include "gdbcmd.h" 27 #include "cli/cli-decode.h" 28 #include "completer.h" 29 #include "language.h" 30 #include "arch-utils.h" 31 32 /* Parameter constants and their values. */ 33 struct parm_constant 34 { 35 char *name; 36 int value; 37 }; 38 39 struct parm_constant parm_constants[] = 40 { 41 { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */ 42 { "PARAM_AUTO_BOOLEAN", var_auto_boolean }, 43 { "PARAM_UINTEGER", var_uinteger }, 44 { "PARAM_INTEGER", var_integer }, 45 { "PARAM_STRING", var_string }, 46 { "PARAM_STRING_NOESCAPE", var_string_noescape }, 47 { "PARAM_OPTIONAL_FILENAME", var_optional_filename }, 48 { "PARAM_FILENAME", var_filename }, 49 { "PARAM_ZINTEGER", var_zinteger }, 50 { "PARAM_ENUM", var_enum }, 51 { NULL, 0 } 52 }; 53 54 /* A union that can hold anything described by enum var_types. */ 55 union parmpy_variable 56 { 57 /* Hold an integer value, for boolean and integer types. */ 58 int intval; 59 60 /* Hold an auto_boolean. */ 61 enum auto_boolean autoboolval; 62 63 /* Hold an unsigned integer value, for uinteger. */ 64 unsigned int uintval; 65 66 /* Hold a string, for the various string types. */ 67 char *stringval; 68 69 /* Hold a string, for enums. */ 70 const char *cstringval; 71 }; 72 73 /* A GDB parameter. */ 74 struct parmpy_object 75 { 76 PyObject_HEAD 77 78 /* The type of the parameter. */ 79 enum var_types type; 80 81 /* The value of the parameter. */ 82 union parmpy_variable value; 83 84 /* For an enum command, the possible values. The vector is 85 allocated with xmalloc, as is each element. It is 86 NULL-terminated. */ 87 const char **enumeration; 88 }; 89 90 typedef struct parmpy_object parmpy_object; 91 92 static PyTypeObject parmpy_object_type; 93 94 /* Some handy string constants. */ 95 static PyObject *set_doc_cst; 96 static PyObject *show_doc_cst; 97 98 99 100 /* Get an attribute. */ 101 static PyObject * 102 get_attr (PyObject *obj, PyObject *attr_name) 103 { 104 if (PyString_Check (attr_name) 105 #ifdef IS_PY3K 106 && ! PyUnicode_CompareWithASCIIString (attr_name, "value")) 107 #else 108 && ! strcmp (PyString_AsString (attr_name), "value")) 109 #endif 110 { 111 parmpy_object *self = (parmpy_object *) obj; 112 113 return gdbpy_parameter_value (self->type, &self->value); 114 } 115 116 return PyObject_GenericGetAttr (obj, attr_name); 117 } 118 119 /* Set a parameter value from a Python value. Return 0 on success. Returns 120 -1 on error, with a python exception set. */ 121 static int 122 set_parameter_value (parmpy_object *self, PyObject *value) 123 { 124 int cmp; 125 126 switch (self->type) 127 { 128 case var_string: 129 case var_string_noescape: 130 case var_optional_filename: 131 case var_filename: 132 if (! gdbpy_is_string (value) 133 && (self->type == var_filename 134 || value != Py_None)) 135 { 136 PyErr_SetString (PyExc_RuntimeError, 137 _("String required for filename.")); 138 139 return -1; 140 } 141 if (value == Py_None) 142 { 143 xfree (self->value.stringval); 144 if (self->type == var_optional_filename) 145 self->value.stringval = xstrdup (""); 146 else 147 self->value.stringval = NULL; 148 } 149 else 150 { 151 char *string; 152 153 string = python_string_to_host_string (value); 154 if (string == NULL) 155 return -1; 156 157 xfree (self->value.stringval); 158 self->value.stringval = string; 159 } 160 break; 161 162 case var_enum: 163 { 164 int i; 165 char *str; 166 167 if (! gdbpy_is_string (value)) 168 { 169 PyErr_SetString (PyExc_RuntimeError, 170 _("ENUM arguments must be a string.")); 171 return -1; 172 } 173 174 str = python_string_to_host_string (value); 175 if (str == NULL) 176 return -1; 177 for (i = 0; self->enumeration[i]; ++i) 178 if (! strcmp (self->enumeration[i], str)) 179 break; 180 xfree (str); 181 if (! self->enumeration[i]) 182 { 183 PyErr_SetString (PyExc_RuntimeError, 184 _("The value must be member of an enumeration.")); 185 return -1; 186 } 187 self->value.cstringval = self->enumeration[i]; 188 break; 189 } 190 191 case var_boolean: 192 if (! PyBool_Check (value)) 193 { 194 PyErr_SetString (PyExc_RuntimeError, 195 _("A boolean argument is required.")); 196 return -1; 197 } 198 cmp = PyObject_IsTrue (value); 199 if (cmp < 0) 200 return -1; 201 self->value.intval = cmp; 202 break; 203 204 case var_auto_boolean: 205 if (! PyBool_Check (value) && value != Py_None) 206 { 207 PyErr_SetString (PyExc_RuntimeError, 208 _("A boolean or None is required")); 209 return -1; 210 } 211 212 if (value == Py_None) 213 self->value.autoboolval = AUTO_BOOLEAN_AUTO; 214 else 215 { 216 cmp = PyObject_IsTrue (value); 217 if (cmp < 0 ) 218 return -1; 219 if (cmp == 1) 220 self->value.autoboolval = AUTO_BOOLEAN_TRUE; 221 else 222 self->value.autoboolval = AUTO_BOOLEAN_FALSE; 223 } 224 break; 225 226 case var_integer: 227 case var_zinteger: 228 case var_uinteger: 229 { 230 long l; 231 int ok; 232 233 if (! PyInt_Check (value)) 234 { 235 PyErr_SetString (PyExc_RuntimeError, 236 _("The value must be integer.")); 237 return -1; 238 } 239 240 if (! gdb_py_int_as_long (value, &l)) 241 return -1; 242 243 if (self->type == var_uinteger) 244 { 245 ok = (l >= 0 && l <= UINT_MAX); 246 if (l == 0) 247 l = UINT_MAX; 248 } 249 else if (self->type == var_integer) 250 { 251 ok = (l >= INT_MIN && l <= INT_MAX); 252 if (l == 0) 253 l = INT_MAX; 254 } 255 else 256 ok = (l >= INT_MIN && l <= INT_MAX); 257 258 if (! ok) 259 { 260 PyErr_SetString (PyExc_RuntimeError, 261 _("Range exceeded.")); 262 return -1; 263 } 264 265 self->value.intval = (int) l; 266 break; 267 } 268 269 default: 270 PyErr_SetString (PyExc_RuntimeError, 271 _("Unhandled type in parameter value.")); 272 return -1; 273 } 274 275 return 0; 276 } 277 278 /* Set an attribute. Returns -1 on error, with a python exception set. */ 279 static int 280 set_attr (PyObject *obj, PyObject *attr_name, PyObject *val) 281 { 282 if (PyString_Check (attr_name) 283 #ifdef IS_PY3K 284 && ! PyUnicode_CompareWithASCIIString (attr_name, "value")) 285 #else 286 && ! strcmp (PyString_AsString (attr_name), "value")) 287 #endif 288 { 289 if (!val) 290 { 291 PyErr_SetString (PyExc_RuntimeError, 292 _("Cannot delete a parameter's value.")); 293 return -1; 294 } 295 return set_parameter_value ((parmpy_object *) obj, val); 296 } 297 298 return PyObject_GenericSetAttr (obj, attr_name, val); 299 } 300 301 /* A helper function which returns a documentation string for an 302 object. */ 303 304 static char * 305 get_doc_string (PyObject *object, PyObject *attr) 306 { 307 char *result = NULL; 308 309 if (PyObject_HasAttr (object, attr)) 310 { 311 PyObject *ds_obj = PyObject_GetAttr (object, attr); 312 313 if (ds_obj && gdbpy_is_string (ds_obj)) 314 { 315 result = python_string_to_host_string (ds_obj); 316 if (result == NULL) 317 gdbpy_print_stack (); 318 } 319 Py_XDECREF (ds_obj); 320 } 321 if (! result) 322 result = xstrdup (_("This command is not documented.")); 323 return result; 324 } 325 326 /* Helper function which will execute a METHOD in OBJ passing the 327 argument ARG. ARG can be NULL. METHOD should return a Python 328 string. If this function returns NULL, there has been an error and 329 the appropriate exception set. */ 330 static char * 331 call_doc_function (PyObject *obj, PyObject *method, PyObject *arg) 332 { 333 char *data = NULL; 334 PyObject *result = PyObject_CallMethodObjArgs (obj, method, arg, NULL); 335 336 if (! result) 337 return NULL; 338 339 if (gdbpy_is_string (result)) 340 { 341 data = python_string_to_host_string (result); 342 Py_DECREF (result); 343 if (! data) 344 return NULL; 345 } 346 else 347 { 348 PyErr_SetString (PyExc_RuntimeError, 349 _("Parameter must return a string value.")); 350 Py_DECREF (result); 351 return NULL; 352 } 353 354 return data; 355 } 356 357 /* A callback function that is registered against the respective 358 add_setshow_* set_doc prototype. This function will either call 359 the Python function "get_set_string" or extract the Python 360 attribute "set_doc" and return the contents as a string. If 361 neither exist, insert a string indicating the Parameter is not 362 documented. */ 363 static void 364 get_set_value (char *args, int from_tty, 365 struct cmd_list_element *c) 366 { 367 PyObject *obj = (PyObject *) get_cmd_context (c); 368 char *set_doc_string; 369 struct cleanup *cleanup = ensure_python_env (get_current_arch (), 370 current_language); 371 PyObject *set_doc_func = PyString_FromString ("get_set_string"); 372 373 if (! set_doc_func) 374 goto error; 375 376 make_cleanup_py_decref (set_doc_func); 377 378 if (PyObject_HasAttr (obj, set_doc_func)) 379 { 380 set_doc_string = call_doc_function (obj, set_doc_func, NULL); 381 if (! set_doc_string) 382 goto error; 383 } 384 else 385 { 386 /* We have to preserve the existing < GDB 7.3 API. If a 387 callback function does not exist, then attempt to read the 388 set_doc attribute. */ 389 set_doc_string = get_doc_string (obj, set_doc_cst); 390 } 391 392 make_cleanup (xfree, set_doc_string); 393 fprintf_filtered (gdb_stdout, "%s\n", set_doc_string); 394 395 do_cleanups (cleanup); 396 return; 397 398 error: 399 gdbpy_print_stack (); 400 do_cleanups (cleanup); 401 return; 402 } 403 404 /* A callback function that is registered against the respective 405 add_setshow_* show_doc prototype. This function will either call 406 the Python function "get_show_string" or extract the Python 407 attribute "show_doc" and return the contents as a string. If 408 neither exist, insert a string indicating the Parameter is not 409 documented. */ 410 static void 411 get_show_value (struct ui_file *file, int from_tty, 412 struct cmd_list_element *c, 413 const char *value) 414 { 415 PyObject *obj = (PyObject *) get_cmd_context (c); 416 char *show_doc_string = NULL; 417 struct cleanup *cleanup = ensure_python_env (get_current_arch (), 418 current_language); 419 PyObject *show_doc_func = PyString_FromString ("get_show_string"); 420 421 if (! show_doc_func) 422 goto error; 423 424 make_cleanup_py_decref (show_doc_func); 425 426 if (PyObject_HasAttr (obj, show_doc_func)) 427 { 428 PyObject *val_obj = PyString_FromString (value); 429 430 if (! val_obj) 431 goto error; 432 433 make_cleanup_py_decref (val_obj); 434 435 show_doc_string = call_doc_function (obj, show_doc_func, val_obj); 436 if (! show_doc_string) 437 goto error; 438 439 make_cleanup (xfree, show_doc_string); 440 441 fprintf_filtered (file, "%s\n", show_doc_string); 442 } 443 else 444 { 445 /* We have to preserve the existing < GDB 7.3 API. If a 446 callback function does not exist, then attempt to read the 447 show_doc attribute. */ 448 show_doc_string = get_doc_string (obj, show_doc_cst); 449 make_cleanup (xfree, show_doc_string); 450 fprintf_filtered (file, "%s %s\n", show_doc_string, value); 451 } 452 453 do_cleanups (cleanup); 454 return; 455 456 error: 457 gdbpy_print_stack (); 458 do_cleanups (cleanup); 459 return; 460 } 461 462 463 /* A helper function that dispatches to the appropriate add_setshow 464 function. */ 465 static void 466 add_setshow_generic (int parmclass, enum command_class cmdclass, 467 char *cmd_name, parmpy_object *self, 468 char *set_doc, char *show_doc, char *help_doc, 469 struct cmd_list_element **set_list, 470 struct cmd_list_element **show_list) 471 { 472 struct cmd_list_element *param = NULL; 473 char *tmp_name = NULL; 474 475 switch (parmclass) 476 { 477 case var_boolean: 478 479 add_setshow_boolean_cmd (cmd_name, cmdclass, 480 &self->value.intval, set_doc, show_doc, 481 help_doc, get_set_value, get_show_value, 482 set_list, show_list); 483 484 break; 485 486 case var_auto_boolean: 487 add_setshow_auto_boolean_cmd (cmd_name, cmdclass, 488 &self->value.autoboolval, 489 set_doc, show_doc, help_doc, 490 get_set_value, get_show_value, 491 set_list, show_list); 492 break; 493 494 case var_uinteger: 495 add_setshow_uinteger_cmd (cmd_name, cmdclass, 496 &self->value.uintval, set_doc, show_doc, 497 help_doc, get_set_value, get_show_value, 498 set_list, show_list); 499 break; 500 501 case var_integer: 502 add_setshow_integer_cmd (cmd_name, cmdclass, 503 &self->value.intval, set_doc, show_doc, 504 help_doc, get_set_value, get_show_value, 505 set_list, show_list); break; 506 507 case var_string: 508 add_setshow_string_cmd (cmd_name, cmdclass, 509 &self->value.stringval, set_doc, show_doc, 510 help_doc, get_set_value, get_show_value, 511 set_list, show_list); break; 512 513 case var_string_noescape: 514 add_setshow_string_noescape_cmd (cmd_name, cmdclass, 515 &self->value.stringval, 516 set_doc, show_doc, help_doc, 517 get_set_value, get_show_value, 518 set_list, show_list); 519 520 break; 521 522 case var_optional_filename: 523 add_setshow_optional_filename_cmd (cmd_name, cmdclass, 524 &self->value.stringval, set_doc, 525 show_doc, help_doc, get_set_value, 526 get_show_value, set_list, 527 show_list); 528 break; 529 530 case var_filename: 531 add_setshow_filename_cmd (cmd_name, cmdclass, 532 &self->value.stringval, set_doc, show_doc, 533 help_doc, get_set_value, get_show_value, 534 set_list, show_list); break; 535 536 case var_zinteger: 537 add_setshow_zinteger_cmd (cmd_name, cmdclass, 538 &self->value.intval, set_doc, show_doc, 539 help_doc, get_set_value, get_show_value, 540 set_list, show_list); 541 break; 542 543 case var_enum: 544 add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration, 545 &self->value.cstringval, set_doc, show_doc, 546 help_doc, get_set_value, get_show_value, 547 set_list, show_list); 548 /* Initialize the value, just in case. */ 549 self->value.cstringval = self->enumeration[0]; 550 break; 551 } 552 553 /* Lookup created parameter, and register Python object against the 554 parameter context. Perform this task against both lists. */ 555 tmp_name = cmd_name; 556 param = lookup_cmd (&tmp_name, *show_list, "", 0, 1); 557 if (param) 558 set_cmd_context (param, self); 559 560 tmp_name = cmd_name; 561 param = lookup_cmd (&tmp_name, *set_list, "", 0, 1); 562 if (param) 563 set_cmd_context (param, self); 564 } 565 566 /* A helper which computes enum values. Returns 1 on success. Returns 0 on 567 error, with a python exception set. */ 568 static int 569 compute_enum_values (parmpy_object *self, PyObject *enum_values) 570 { 571 Py_ssize_t size, i; 572 struct cleanup *back_to; 573 574 if (! enum_values) 575 { 576 PyErr_SetString (PyExc_RuntimeError, 577 _("An enumeration is required for PARAM_ENUM.")); 578 return 0; 579 } 580 581 if (! PySequence_Check (enum_values)) 582 { 583 PyErr_SetString (PyExc_RuntimeError, 584 _("The enumeration is not a sequence.")); 585 return 0; 586 } 587 588 size = PySequence_Size (enum_values); 589 if (size < 0) 590 return 0; 591 if (size == 0) 592 { 593 PyErr_SetString (PyExc_RuntimeError, 594 _("The enumeration is empty.")); 595 return 0; 596 } 597 598 self->enumeration = xmalloc ((size + 1) * sizeof (char *)); 599 back_to = make_cleanup (free_current_contents, &self->enumeration); 600 memset (self->enumeration, 0, (size + 1) * sizeof (char *)); 601 602 for (i = 0; i < size; ++i) 603 { 604 PyObject *item = PySequence_GetItem (enum_values, i); 605 606 if (! item) 607 { 608 do_cleanups (back_to); 609 return 0; 610 } 611 if (! gdbpy_is_string (item)) 612 { 613 do_cleanups (back_to); 614 PyErr_SetString (PyExc_RuntimeError, 615 _("The enumeration item not a string.")); 616 return 0; 617 } 618 self->enumeration[i] = python_string_to_host_string (item); 619 if (self->enumeration[i] == NULL) 620 { 621 do_cleanups (back_to); 622 return 0; 623 } 624 make_cleanup (xfree, (char *) self->enumeration[i]); 625 } 626 627 discard_cleanups (back_to); 628 return 1; 629 } 630 631 /* Object initializer; sets up gdb-side structures for command. 632 633 Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM]) 634 635 NAME is the name of the parameter. It may consist of multiple 636 words, in which case the final word is the name of the new command, 637 and earlier words must be prefix commands. 638 639 CMDCLASS is the kind of command. It should be one of the COMMAND_* 640 constants defined in the gdb module. 641 642 PARMCLASS is the type of the parameter. It should be one of the 643 PARAM_* constants defined in the gdb module. 644 645 If PARMCLASS is PARAM_ENUM, then the final argument should be a 646 collection of strings. These strings are the valid values for this 647 parameter. 648 649 The documentation for the parameter is taken from the doc string 650 for the python class. 651 652 Returns -1 on error, with a python exception set. */ 653 654 static int 655 parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) 656 { 657 parmpy_object *obj = (parmpy_object *) self; 658 const char *name; 659 char *set_doc, *show_doc, *doc; 660 char *cmd_name; 661 int parmclass, cmdtype; 662 PyObject *enum_values = NULL; 663 struct cmd_list_element **set_list, **show_list; 664 volatile struct gdb_exception except; 665 666 if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass, 667 &enum_values)) 668 return -1; 669 670 if (cmdtype != no_class && cmdtype != class_run 671 && cmdtype != class_vars && cmdtype != class_stack 672 && cmdtype != class_files && cmdtype != class_support 673 && cmdtype != class_info && cmdtype != class_breakpoint 674 && cmdtype != class_trace && cmdtype != class_obscure 675 && cmdtype != class_maintenance) 676 { 677 PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument.")); 678 return -1; 679 } 680 681 if (parmclass != var_boolean /* ARI: var_boolean */ 682 && parmclass != var_auto_boolean 683 && parmclass != var_uinteger && parmclass != var_integer 684 && parmclass != var_string && parmclass != var_string_noescape 685 && parmclass != var_optional_filename && parmclass != var_filename 686 && parmclass != var_zinteger && parmclass != var_enum) 687 { 688 PyErr_SetString (PyExc_RuntimeError, 689 _("Invalid parameter class argument.")); 690 return -1; 691 } 692 693 if (enum_values && parmclass != var_enum) 694 { 695 PyErr_SetString (PyExc_RuntimeError, 696 _("Only PARAM_ENUM accepts a fourth argument.")); 697 return -1; 698 } 699 if (parmclass == var_enum) 700 { 701 if (! compute_enum_values (obj, enum_values)) 702 return -1; 703 } 704 else 705 obj->enumeration = NULL; 706 obj->type = (enum var_types) parmclass; 707 memset (&obj->value, 0, sizeof (obj->value)); 708 709 cmd_name = gdbpy_parse_command_name (name, &set_list, 710 &setlist); 711 712 if (! cmd_name) 713 return -1; 714 xfree (cmd_name); 715 cmd_name = gdbpy_parse_command_name (name, &show_list, 716 &showlist); 717 if (! cmd_name) 718 return -1; 719 720 set_doc = get_doc_string (self, set_doc_cst); 721 show_doc = get_doc_string (self, show_doc_cst); 722 doc = get_doc_string (self, gdbpy_doc_cst); 723 724 Py_INCREF (self); 725 726 TRY_CATCH (except, RETURN_MASK_ALL) 727 { 728 add_setshow_generic (parmclass, (enum command_class) cmdtype, 729 cmd_name, obj, 730 set_doc, show_doc, 731 doc, set_list, show_list); 732 } 733 if (except.reason < 0) 734 { 735 xfree (cmd_name); 736 xfree (set_doc); 737 xfree (show_doc); 738 xfree (doc); 739 Py_DECREF (self); 740 PyErr_Format (except.reason == RETURN_QUIT 741 ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, 742 "%s", except.message); 743 return -1; 744 } 745 return 0; 746 } 747 748 749 750 /* Initialize the 'parameters' module. */ 751 void 752 gdbpy_initialize_parameters (void) 753 { 754 int i; 755 756 parmpy_object_type.tp_new = PyType_GenericNew; 757 if (PyType_Ready (&parmpy_object_type) < 0) 758 return; 759 760 set_doc_cst = PyString_FromString ("set_doc"); 761 if (! set_doc_cst) 762 return; 763 show_doc_cst = PyString_FromString ("show_doc"); 764 if (! show_doc_cst) 765 return; 766 767 for (i = 0; parm_constants[i].name; ++i) 768 { 769 if (PyModule_AddIntConstant (gdb_module, 770 parm_constants[i].name, 771 parm_constants[i].value) < 0) 772 return; 773 } 774 775 Py_INCREF (&parmpy_object_type); 776 PyModule_AddObject (gdb_module, "Parameter", 777 (PyObject *) &parmpy_object_type); 778 } 779 780 781 782 static PyTypeObject parmpy_object_type = 783 { 784 PyVarObject_HEAD_INIT (NULL, 0) 785 "gdb.Parameter", /*tp_name*/ 786 sizeof (parmpy_object), /*tp_basicsize*/ 787 0, /*tp_itemsize*/ 788 0, /*tp_dealloc*/ 789 0, /*tp_print*/ 790 0, /*tp_getattr*/ 791 0, /*tp_setattr*/ 792 0, /*tp_compare*/ 793 0, /*tp_repr*/ 794 0, /*tp_as_number*/ 795 0, /*tp_as_sequence*/ 796 0, /*tp_as_mapping*/ 797 0, /*tp_hash */ 798 0, /*tp_call*/ 799 0, /*tp_str*/ 800 get_attr, /*tp_getattro*/ 801 set_attr, /*tp_setattro*/ 802 0, /*tp_as_buffer*/ 803 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 804 "GDB parameter object", /* tp_doc */ 805 0, /* tp_traverse */ 806 0, /* tp_clear */ 807 0, /* tp_richcompare */ 808 0, /* tp_weaklistoffset */ 809 0, /* tp_iter */ 810 0, /* tp_iternext */ 811 0, /* tp_methods */ 812 0, /* tp_members */ 813 0, /* tp_getset */ 814 0, /* tp_base */ 815 0, /* tp_dict */ 816 0, /* tp_descr_get */ 817 0, /* tp_descr_set */ 818 0, /* tp_dictoffset */ 819 parmpy_init, /* tp_init */ 820 0, /* tp_alloc */ 821 }; 822