diff options
author | Erlend Egeberg Aasland <erlend.aasland@innova.no> | 2020-11-20 12:36:23 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-20 12:36:23 (GMT) |
commit | a6109ef68d421712ba368ef502c4789e8de113e0 (patch) | |
tree | 6774e1a1d55f671febbd23e2a393339f35adb70a /Modules/_sre.c | |
parent | 2db8e35489d63b976a463fb1d2a6c29f4f965c21 (diff) | |
download | cpython-a6109ef68d421712ba368ef502c4789e8de113e0.zip cpython-a6109ef68d421712ba368ef502c4789e8de113e0.tar.gz cpython-a6109ef68d421712ba368ef502c4789e8de113e0.tar.bz2 |
bpo-1635741: Convert _sre types to heap types and establish module state (PEP 384) (GH-23393)
Diffstat (limited to 'Modules/_sre.c')
-rw-r--r-- | Modules/_sre.c | 473 |
1 files changed, 275 insertions, 198 deletions
diff --git a/Modules/_sre.c b/Modules/_sre.c index fbabeb7..0a5ca60 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -248,22 +248,36 @@ data_stack_grow(SRE_STATE* state, Py_ssize_t size) /* -------------------------------------------------------------------- */ /* factories and destructors */ -/* see sre.h for object declarations */ -static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); +/* module state */ +typedef struct { + PyTypeObject *Pattern_Type; + PyTypeObject *Match_Type; + PyTypeObject *Scanner_Type; +} _sremodulestate; + +static _sremodulestate * +get_sre_module_state(PyObject *m) +{ + _sremodulestate *state = (_sremodulestate *)PyModule_GetState(m); + assert(state); + return state; +} +static struct PyModuleDef sremodule; +#define get_sre_module_state_by_class(cls) \ + (get_sre_module_state(PyType_GetModule(cls))) + +/* see sre.h for object declarations */ +static PyObject*pattern_new_match(_sremodulestate *, PatternObject*, SRE_STATE*, Py_ssize_t); +static PyObject *pattern_scanner(_sremodulestate *, PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "&Pattern_Type" -class _sre.SRE_Match "MatchObject *" "&Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" +class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_class(tp)->Pattern_Type" +class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_class(tp)->Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_class(tp)->Scanner_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ - -static PyTypeObject Pattern_Type; -static PyTypeObject Match_Type; -static PyTypeObject Scanner_Type; +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fe2966e32b66a231]*/ /*[clinic input] _sre.getcodesize -> int @@ -550,12 +564,15 @@ pattern_error(Py_ssize_t status) static void pattern_dealloc(PatternObject* self) { + PyTypeObject *tp = Py_TYPE(self); + if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_XDECREF(self->pattern); Py_XDECREF(self->groupindex); Py_XDECREF(self->indexgroup); PyObject_DEL(self); + Py_DECREF(tp); } LOCAL(Py_ssize_t) @@ -583,6 +600,8 @@ sre_search(SRE_STATE* state, SRE_CODE* pattern) /*[clinic input] _sre.SRE_Pattern.match + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -591,10 +610,12 @@ Matches zero or more characters at the beginning of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=ea2d838888510661 input=a2ba191647abebe5]*/ +_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=ec6208ea58a0cca0 input=4bdb9c3e564d13ac]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -614,7 +635,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -622,6 +643,8 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.fullmatch + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -630,10 +653,12 @@ Matches against all of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=5833c47782a35f4a input=d9fb03a7625b5828]*/ +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=625b75b027ef94da input=50981172ab0fcfdd]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -654,7 +679,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -662,6 +687,8 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.search + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -672,10 +699,12 @@ Return None if no position in the string matches. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=25f302a644e951e8 input=4ae5cb7dc38fed1b]*/ +_sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=bd7f2d9d583e1463 input=afa9afb66a74a4b3]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -694,7 +723,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -826,6 +855,8 @@ error: /*[clinic input] _sre.SRE_Pattern.finditer + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -836,15 +867,17 @@ For each match, the iterator returns a match object. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=0bbb1a0aeb38bb14 input=612aab69e9fe08e4]*/ +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=1791dbf3618ade56 input=812e332a4848cbaf]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); PyObject* scanner; PyObject* search; PyObject* iterator; - scanner = pattern_scanner(self, string, pos, endpos); + scanner = pattern_scanner(module_state, self, string, pos, endpos); if (!scanner) return NULL; @@ -862,6 +895,8 @@ _sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.scanner + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -869,11 +904,14 @@ _sre.SRE_Pattern.scanner [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=54ea548aed33890b input=3aacdbde77a3a637]*/ +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=f70cd506112f1bd9 input=2e487e5151bcee4c]*/ { - return pattern_scanner(self, string, pos, endpos); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_scanner(module_state, self, string, pos, endpos); } /*[clinic input] @@ -980,8 +1018,12 @@ error: } static PyObject* -pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, - Py_ssize_t count, Py_ssize_t subn) +pattern_subx(_sremodulestate* module_state, + PatternObject* self, + PyObject* ptemplate, + PyObject* string, + Py_ssize_t count, + Py_ssize_t subn) { SRE_STATE state; PyObject* list; @@ -1083,7 +1125,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, if (filter_is_callable) { /* pass match object through filter */ - match = pattern_new_match(self, &state, 1); + match = pattern_new_match(module_state, self, &state, 1); if (!match) goto error; item = PyObject_CallOneArg(filter, match); @@ -1163,6 +1205,8 @@ error: /*[clinic input] _sre.SRE_Pattern.sub + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1171,16 +1215,20 @@ Return the string obtained by replacing the leftmost non-overlapping occurrences [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=1dbf2ec3479cba00 input=c53d70be0b3caf86]*/ +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, Py_ssize_t count) +/*[clinic end generated code: output=4be141ab04bca60d input=d8d1d4ac2311a07c]*/ { - return pattern_subx(self, repl, string, count, 0); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 0); } /*[clinic input] _sre.SRE_Pattern.subn + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1189,11 +1237,14 @@ Return the tuple (new_string, number_of_subs_made) found by replacing the leftmo [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=0d9522cd529e9728 input=e7342d7ce6083577]*/ +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, + Py_ssize_t count) +/*[clinic end generated code: output=da02fd85258b1e1f input=8b78a65b8302e58d]*/ { - return pattern_subx(self, repl, string, count, 1); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 1); } /*[clinic input] @@ -1338,12 +1389,13 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, { /* "compile" pattern descriptor to pattern object */ + _sremodulestate *module_state = get_sre_module_state(module); PatternObject* self; Py_ssize_t i, n; n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, &Pattern_Type, n); + self = PyObject_NewVar(PatternObject, module_state->Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -1887,10 +1939,13 @@ _validate(PatternObject *self) static void match_dealloc(MatchObject* self) { + PyTypeObject *tp = Py_TYPE(self); + Py_XDECREF(self->regs); Py_XDECREF(self->string); Py_DECREF(self->pattern); PyObject_DEL(self); + Py_DECREF(tp); } static PyObject* @@ -2319,7 +2374,10 @@ match_repr(MatchObject *self) static PyObject* -pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) +pattern_new_match(_sremodulestate* module_state, + PatternObject* pattern, + SRE_STATE* state, + Py_ssize_t status) { /* create match object (from state object) */ @@ -2332,7 +2390,8 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, &Match_Type, + match = PyObject_NewVar(MatchObject, + module_state->Match_Type, 2*(pattern->groups+1)); if (!match) return NULL; @@ -2387,20 +2446,27 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) static void scanner_dealloc(ScannerObject* self) { + PyTypeObject *tp = Py_TYPE(self); + state_fini(&self->state); Py_XDECREF(self->pattern); PyObject_DEL(self); + Py_DECREF(tp); } /*[clinic input] _sre.SRE_Scanner.match + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self) -/*[clinic end generated code: output=936b30c63d4b81eb input=881a0154f8c13d9a]*/ +_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=6e22c149dc0f0325 input=b5146e1f30278cb7]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2416,8 +2482,8 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) if (PyErr_Occurred()) return NULL; - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2433,12 +2499,16 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) /*[clinic input] _sre.SRE_Scanner.search + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_search_impl(ScannerObject *self) -/*[clinic end generated code: output=7dc211986088f025 input=161223ee92ef9270]*/ +_sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=23e8fc78013f9161 input=056c2d37171d0bf2]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2454,8 +2524,8 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) if (PyErr_Occurred()) return NULL; - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2468,12 +2538,16 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) } static PyObject * -pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos) +pattern_scanner(_sremodulestate *module_state, + PatternObject *self, + PyObject *string, + Py_ssize_t pos, + Py_ssize_t endpos) { ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, &Scanner_Type); + scanner = PyObject_New(ScannerObject, module_state->Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2516,6 +2590,8 @@ pattern_hash(PatternObject *self) static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { + PyTypeObject *tp = Py_TYPE(lefto); + _sremodulestate *module_state = get_sre_module_state_by_class(tp); PatternObject *left, *right; int cmp; @@ -2523,7 +2599,8 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) Py_RETURN_NOTIMPLEMENTED; } - if (!Py_IS_TYPE(lefto, &Pattern_Type) || !Py_IS_TYPE(righto, &Pattern_Type)) { + if (!Py_IS_TYPE(righto, module_state->Pattern_Type)) + { Py_RETURN_NOTIMPLEMENTED; } @@ -2592,47 +2669,28 @@ static PyMemberDef pattern_members[] = { "The regex matching flags."}, {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY, "The number of capturing groups in the pattern."}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(PatternObject, weakreflist), READONLY}, {NULL} /* Sentinel */ }; -static PyTypeObject Pattern_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "re.Pattern", - sizeof(PatternObject), sizeof(SRE_CODE), - (destructor)pattern_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)pattern_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)pattern_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - pattern_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - pattern_richcompare, /* tp_richcompare */ - offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pattern_methods, /* tp_methods */ - pattern_members, /* tp_members */ - pattern_getset, /* tp_getset */ +static PyType_Slot pattern_slots[] = { + {Py_tp_dealloc, (destructor)pattern_dealloc}, + {Py_tp_repr, (reprfunc)pattern_repr}, + {Py_tp_hash, (hashfunc)pattern_hash}, + {Py_tp_doc, (void *)pattern_doc}, + {Py_tp_richcompare, pattern_richcompare}, + {Py_tp_methods, pattern_methods}, + {Py_tp_members, pattern_members}, + {Py_tp_getset, pattern_getset}, + {0, NULL}, }; -/* Match objects do not support length or assignment, but do support - __getitem__. */ -static PyMappingMethods match_as_mapping = { - NULL, - (binaryfunc)match_getitem, - NULL +static PyType_Spec pattern_spec = { + .name = "re.Pattern", + .basicsize = sizeof(PatternObject), + .itemsize = sizeof(SRE_CODE), + .flags = Py_TPFLAGS_DEFAULT, + .slots = pattern_slots, }; static PyMethodDef match_methods[] = { @@ -2674,37 +2732,30 @@ static PyMemberDef match_members[] = { /* FIXME: implement setattr("string", None) as a special case (to detach the associated string, if any */ +static PyType_Slot match_slots[] = { + {Py_tp_dealloc, match_dealloc}, + {Py_tp_repr, match_repr}, + {Py_tp_doc, (void *)match_doc}, + {Py_tp_methods, match_methods}, + {Py_tp_members, match_members}, + {Py_tp_getset, match_getset}, + + /* As mapping. + * + * Match objects do not support length or assignment, but do support + * __getitem__. + */ + {Py_mp_subscript, match_getitem}, + + {0, NULL}, +}; -static PyTypeObject Match_Type = { - PyVarObject_HEAD_INIT(NULL,0) - "re.Match", - sizeof(MatchObject), sizeof(Py_ssize_t), - (destructor)match_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)match_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - &match_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - match_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - match_methods, /* tp_methods */ - match_members, /* tp_members */ - match_getset, /* tp_getset */ +static PyType_Spec match_spec = { + .name = "re.Match", + .basicsize = sizeof(MatchObject), + .itemsize = sizeof(Py_ssize_t), + .flags = Py_TPFLAGS_DEFAULT, + .slots = match_slots, }; static PyMethodDef scanner_methods[] = { @@ -2719,36 +2770,18 @@ static PyMemberDef scanner_members[] = { {NULL} /* Sentinel */ }; -static PyTypeObject Scanner_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_" SRE_MODULE ".SRE_Scanner", - sizeof(ScannerObject), 0, - (destructor)scanner_dealloc,/* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 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 */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - scanner_methods, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ +static PyType_Slot scanner_slots[] = { + {Py_tp_dealloc, scanner_dealloc}, + {Py_tp_methods, scanner_methods}, + {Py_tp_members, scanner_members}, + {0, NULL}, +}; + +static PyType_Spec scanner_spec = { + .name = "_" SRE_MODULE ".SRE_Scanner", + .basicsize = sizeof(ScannerObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = scanner_slots, }; static PyMethodDef _functions[] = { @@ -2761,64 +2794,108 @@ static PyMethodDef _functions[] = { {NULL, NULL} }; -static struct PyModuleDef sremodule = { - PyModuleDef_HEAD_INIT, - "_" SRE_MODULE, - NULL, - -1, - _functions, - NULL, - NULL, - NULL, - NULL -}; +static int +sre_traverse(PyObject *module, visitproc visit, void *arg) +{ + _sremodulestate *state = get_sre_module_state(module); + + Py_VISIT(state->Pattern_Type); + Py_VISIT(state->Match_Type); + Py_VISIT(state->Scanner_Type); + + return 0; +} -PyMODINIT_FUNC PyInit__sre(void) +static int +sre_clear(PyObject *module) { - PyObject* m; - PyObject* d; - PyObject* x; + _sremodulestate *state = get_sre_module_state(module); - /* Patch object types */ - if (PyType_Ready(&Pattern_Type) || PyType_Ready(&Match_Type) || - PyType_Ready(&Scanner_Type)) - return NULL; + Py_CLEAR(state->Pattern_Type); + Py_CLEAR(state->Match_Type); + Py_CLEAR(state->Scanner_Type); - m = PyModule_Create(&sremodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); + return 0; +} - x = PyLong_FromLong(SRE_MAGIC); - if (x) { - PyDict_SetItemString(d, "MAGIC", x); - Py_DECREF(x); - } +static void +sre_free(void *module) +{ + sre_clear((PyObject *)module); +} + +#define CREATE_TYPE(m, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(m, spec, NULL); \ + if (type == NULL) { \ + goto error; \ + } \ +} while (0) + +#define ADD_ULONG_CONSTANT(module, name, value) \ + do { \ + PyObject *o = PyLong_FromUnsignedLong(value); \ + if (!o) \ + goto error; \ + int res = PyModule_AddObjectRef(module, name, o); \ + Py_DECREF(o); \ + if (res < 0) { \ + goto error; \ + } \ +} while (0) - x = PyLong_FromLong(sizeof(SRE_CODE)); - if (x) { - PyDict_SetItemString(d, "CODESIZE", x); - Py_DECREF(x); - } +static int +sre_exec(PyObject *m) +{ + _sremodulestate *state; + + /* Create heap types */ + state = get_sre_module_state(m); + CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); + CREATE_TYPE(m, state->Match_Type, &match_spec); + CREATE_TYPE(m, state->Scanner_Type, &scanner_spec); - x = PyLong_FromUnsignedLong(SRE_MAXREPEAT); - if (x) { - PyDict_SetItemString(d, "MAXREPEAT", x); - Py_DECREF(x); + if (PyModule_AddIntConstant(m, "MAGIC", SRE_MAGIC) < 0) { + goto error; } - x = PyLong_FromUnsignedLong(SRE_MAXGROUPS); - if (x) { - PyDict_SetItemString(d, "MAXGROUPS", x); - Py_DECREF(x); + if (PyModule_AddIntConstant(m, "CODESIZE", sizeof(SRE_CODE)) < 0) { + goto error; } - x = PyUnicode_FromString(copyright); - if (x) { - PyDict_SetItemString(d, "copyright", x); - Py_DECREF(x); + ADD_ULONG_CONSTANT(m, "MAXREPEAT", SRE_MAXREPEAT); + ADD_ULONG_CONSTANT(m, "MAXGROUPS", SRE_MAXGROUPS); + + if (PyModule_AddStringConstant(m, "copyright", copyright) < 0) { + goto error; } - return m; + + return 0; + +error: + return -1; +} + +static PyModuleDef_Slot sre_slots[] = { + {Py_mod_exec, sre_exec}, + {0, NULL}, +}; + +static struct PyModuleDef sremodule = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_" SRE_MODULE, + .m_size = sizeof(_sremodulestate), + .m_methods = _functions, + .m_slots = sre_slots, + .m_traverse = sre_traverse, + .m_free = sre_free, + .m_clear = sre_clear, +}; + +PyMODINIT_FUNC +PyInit__sre(void) +{ + return PyModuleDef_Init(&sremodule); } /* vim:ts=4:sw=4:et |