diff -r ac08e796cd37 Modules/parsermodule.c --- a/Modules/parsermodule.c Fri Dec 14 19:39:29 2012 +0100 +++ b/Modules/parsermodule.c Fri Dec 14 19:40:29 2012 +0100 @@ -45,6 +45,41 @@ #define NOTE(x) #endif +typedef struct { + PyObject *PyST_Type; + PyObject *parser_error; +} parserstate; + + +#define parser_state(o) ((parserstate *)PyModule_GetState(o)) + +static int +parser_clear(PyObject *m) +{ + Py_CLEAR(parser_state(m)->parser_error); + Py_CLEAR(parser_state(m)->PyST_Type); + return 0; +} + +static int +parser_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(parser_state(m)->parser_error); + Py_VISIT(parser_state(m)->PyST_Type); + return 0; +} + +static void +parser_free(void *m) +{ + parser_clear((PyObject *)m); +} + +static PyModuleDef parsermodule; + +#define parserstate_global ((parserstate *)PyModule_GetState(PyState_FindModule(&parsermodule))) + + /* String constants used to initialize module attributes. * */ @@ -154,10 +189,6 @@ * naming style, but the code uses the new naming convention. */ -static PyObject* -parser_error = 0; - - typedef struct { PyObject_HEAD /* standard object header */ node* st_node; /* the node* returned by the parser */ @@ -166,7 +197,7 @@ } PyST_Object; -static void parser_free(PyST_Object *st); +static void parser_dealloc(PyST_Object *st); static PyObject* parser_sizeof(PyST_Object *, void *); static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op); static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *); @@ -193,46 +224,28 @@ {NULL, NULL, 0, NULL} }; -static -PyTypeObject PyST_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "parser.st", /* tp_name */ - (int) sizeof(PyST_Object), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)parser_free, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - - /* Functions to access object as input/output buffer */ - 0, /* tp_as_buffer */ - - Py_TPFLAGS_DEFAULT, /* tp_flags */ - - /* __doc__ */ - "Intermediate representation of a Python parse tree.", - 0, /* tp_traverse */ - 0, /* tp_clear */ - parser_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - parser_methods, /* tp_methods */ -}; /* PyST_Type */ + + +static PyType_Slot PyST_Type_slots[] = { + {Py_tp_dealloc, (destructor)parser_dealloc}, + {Py_tp_doc, "Intermediate representation of a Python parse tree."}, + {Py_tp_richcompare, parser_richcompare}, + {Py_tp_methods, parser_methods}, + {0, 0} +}; + +static PyType_Spec PyST_Type_spec = { + "parser.st", + (int) sizeof(PyST_Object), + 0, + Py_TPFLAGS_DEFAULT, + PyST_Type_slots, +}; + /* PyST_Type */ /* PyST_Type isn't subclassable, so just check ob_type */ -#define PyST_Object_Check(v) ((v)->ob_type == &PyST_Type) +#define PyST_Object_Check(v) ((v)->ob_type == (PyTypeObject *)parserstate_global->PyST_Type) static int parser_compare_nodes(node *left, node *right) @@ -337,7 +350,9 @@ static PyObject* parser_newstobject(node *st, int type) { - PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type); + PyST_Object* o = PyObject_New(PyST_Object, + (PyTypeObject *)parserstate_global->PyST_Type); + Py_INCREF(parserstate_global->PyST_Type); if (o != 0) { o->st_node = st; @@ -351,15 +366,19 @@ } -/* void parser_free(PyST_Object* st) +/* void parser_dealloc(PyST_Object* st) * * This is called by a del statement that reduces the reference count to 0. * */ static void -parser_free(PyST_Object *st) +parser_dealloc(PyST_Object *st) { + PyTypeObject *type = Py_TYPE(st); PyNode_Free(st->st_node); + if((void *)type->tp_dealloc == (void *)parser_dealloc) { + Py_DECREF(type); + } PyObject_Del(st); } @@ -391,7 +410,7 @@ if (self == NULL || PyModule_Check(self)) { ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2tuple", keywords, - &PyST_Type, &self, &line_info, + parserstate_global->PyST_Type, &self, &line_info, &col_info); } else @@ -427,7 +446,7 @@ if (self == NULL || PyModule_Check(self)) ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2list", keywords, - &PyST_Type, &self, &line_info, + parserstate_global->PyST_Type, &self, &line_info, &col_info); else ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:tolist", &keywords[1], @@ -463,7 +482,7 @@ if (self == NULL || PyModule_Check(self)) ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords, - &PyST_Type, &self, &str); + parserstate_global->PyST_Type, &self, &str); else ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1], &str); @@ -500,7 +519,7 @@ if (self == NULL || PyModule_Check(self)) ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords, - &PyST_Type, &self); + parserstate_global->PyST_Type, &self); else ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]); @@ -523,7 +542,7 @@ if (self == NULL || PyModule_Check(self)) ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:issuite", keywords, - &PyST_Type, &self); + parserstate_global->PyST_Type, &self); else ok = PyArg_ParseTupleAndKeywords(args, kw, ":issuite", &keywords[1]); @@ -544,7 +563,7 @@ static void err_string(char *message) { - PyErr_SetString(parser_error, message); + PyErr_SetString(parserstate_global->parser_error, message); } @@ -744,7 +763,7 @@ if (!ok) { PyObject *err = Py_BuildValue("os", elem, "Illegal node construct."); - PyErr_SetObject(parser_error, err); + PyErr_SetObject(parserstate_global->parser_error, err); Py_XDECREF(err); Py_XDECREF(elem); return (0); @@ -762,7 +781,7 @@ if (temp == NULL) return 0; if (!PyUnicode_Check(temp)) { - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "second item in terminal node must be a string," " found %s", Py_TYPE(temp)->tp_name); @@ -776,7 +795,7 @@ if (PyLong_Check(o)) *line_num = PyLong_AS_LONG(o); else { - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "third item in terminal node must be an" " integer, found %s", Py_TYPE(temp)->tp_name); @@ -805,7 +824,7 @@ * Throw an exception. */ PyObject *err = Py_BuildValue("os", elem, "unknown node type."); - PyErr_SetObject(parser_error, err); + PyErr_SetObject(parserstate_global->parser_error, err); Py_XDECREF(err); Py_XDECREF(elem); return (0); @@ -858,7 +877,7 @@ */ tuple = Py_BuildValue("os", tuple, "Illegal syntax-tree; cannot start with terminal symbol."); - PyErr_SetObject(parser_error, tuple); + PyErr_SetObject(parserstate_global->parser_error, tuple); Py_XDECREF(tuple); } else if (ISNONTERMINAL(num)) { @@ -906,7 +925,7 @@ */ PyObject *err = Py_BuildValue("os", tuple, "Illegal component tuple."); - PyErr_SetObject(parser_error, err); + PyErr_SetObject(parserstate_global->parser_error, err); Py_XDECREF(err); } @@ -985,7 +1004,7 @@ validate_ntype(node *n, int t) { if (TYPE(n) != t) { - PyErr_Format(parser_error, "Expected node type %d, got %d.", + PyErr_Format(parserstate_global->parser_error, "Expected node type %d, got %d.", t, TYPE(n)); return 0; } @@ -1004,7 +1023,7 @@ validate_numnodes(node *n, int num, const char *const name) { if (NCH(n) != num) { - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Illegal number of children for %s node.", name); return 0; } @@ -1019,7 +1038,7 @@ && ((string == 0) || (strcmp(string, STR(terminal)) == 0))); if (!res && !PyErr_Occurred()) { - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Illegal terminal: expected \"%s\"", string); } return (res); @@ -1486,7 +1505,7 @@ } else if (nch == 1) { res = 0; - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Unrecognized child node of small_stmt: %d.", TYPE(CHILD(tree, 0))); } @@ -1520,7 +1539,7 @@ res = validate_node(tree); else { res = 0; - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Illegal compound statement type: %d.", TYPE(tree)); } return (res); @@ -1852,7 +1871,7 @@ } else if (nch == 1) { res = 0; - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Unrecognized child node of import_stmt: %d.", TYPE(CHILD(tree, 0))); } @@ -2000,7 +2019,7 @@ if (TYPE(CHILD(tree, nch - 3)) != except_clause) name = STR(CHILD(tree, nch - 3)); - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "Illegal number of children for try/%s node.", name); } /* Handle try/finally statement */ @@ -2184,7 +2203,7 @@ res = ((strcmp(STR(tree), "in") == 0) || (strcmp(STR(tree), "is") == 0)); if (!res) { - PyErr_Format(parser_error, + PyErr_Format(parserstate_global->parser_error, "illegal operator '%s'", STR(tree)); } break; @@ -3247,7 +3266,7 @@ PyObject *st = NULL; PyObject *empty_dict = NULL; - if (PyArg_ParseTuple(args, "O!:_pickler", &PyST_Type, &st)) { + if (PyArg_ParseTuple(args, "O!:_pickler", parserstate_global->PyST_Type, &st)) { PyObject *newargs; PyObject *tuple; @@ -3309,12 +3328,12 @@ PyModuleDef_HEAD_INIT, "parser", NULL, - -1, + sizeof(parserstate), parser_functions, NULL, - NULL, - NULL, - NULL + parser_traverse, + parser_clear, + parser_free }; PyMODINIT_FUNC PyInit_parser(void); /* supply a prototype */ @@ -3324,16 +3343,18 @@ { PyObject *module, *copyreg; - if (PyType_Ready(&PyST_Type) < 0) - return NULL; module = PyModule_Create(&parsermodule); if (module == NULL) return NULL; - if (parser_error == 0) - parser_error = PyErr_NewException("parser.ParserError", NULL, NULL); - - if (parser_error == 0) + parser_state(module)->PyST_Type = PyType_FromSpec(&PyST_Type_spec); + if (parser_state(module)->PyST_Type == NULL) + return NULL; + + if (parser_state(module)->parser_error == 0) + parser_state(module)->parser_error = PyErr_NewException("parser.ParserError", NULL, NULL); + + if (parser_state(module)->parser_error == 0) return NULL; /* CAUTION: The code next used to skip bumping the refcount on * parser_error. That's a disaster if PyInit_parser() gets called more @@ -3341,12 +3362,12 @@ * gets created owns its reference to the shared parser_error object, * and the file static parser_error vrbl owns a reference too. */ - Py_INCREF(parser_error); - if (PyModule_AddObject(module, "ParserError", parser_error) != 0) + Py_INCREF(parser_state(module)->parser_error); + if (PyModule_AddObject(module, "ParserError", parser_state(module)->parser_error) != 0) return NULL; - Py_INCREF(&PyST_Type); - PyModule_AddObject(module, "STType", (PyObject*)&PyST_Type); + Py_INCREF(parser_state(module)->PyST_Type); + PyModule_AddObject(module, "STType", parser_state(module)->PyST_Type); PyModule_AddStringConstant(module, "__copyright__", parser_copyright_string); @@ -3374,7 +3395,7 @@ && (pickler != NULL)) { PyObject *res; - res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler, + res = PyObject_CallFunctionObjArgs(func, parser_state(module)->PyST_Type, pickler, pickle_constructor, NULL); Py_XDECREF(res); }