|
15 | 15 |
|
16 | 16 | #include "Python.h" |
17 | 17 | #include "structmember.h" // PyMemberDef |
| 18 | +#include "expat.h" |
| 19 | +#include "pyexpat.h" |
18 | 20 |
|
19 | 21 | /* -------------------------------------------------------------------- */ |
20 | 22 | /* configuration */ |
@@ -90,6 +92,8 @@ typedef struct { |
90 | 92 | PyTypeObject *ElementIter_Type; |
91 | 93 | PyTypeObject *TreeBuilder_Type; |
92 | 94 | PyTypeObject *XMLParser_Type; |
| 95 | + |
| 96 | + struct PyExpat_CAPI *expat_capi; |
93 | 97 | } elementtreestate; |
94 | 98 |
|
95 | 99 | static struct PyModuleDef elementtreemodule; |
@@ -146,6 +150,8 @@ elementtree_clear(PyObject *m) |
146 | 150 | Py_CLEAR(st->ElementIter_Type); |
147 | 151 | Py_CLEAR(st->TreeBuilder_Type); |
148 | 152 | Py_CLEAR(st->XMLParser_Type); |
| 153 | + |
| 154 | + st->expat_capi = NULL; |
149 | 155 | return 0; |
150 | 156 | } |
151 | 157 |
|
@@ -3031,14 +3037,7 @@ _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, |
3031 | 3037 | /* ==================================================================== */ |
3032 | 3038 | /* the expat interface */ |
3033 | 3039 |
|
3034 | | -#include "expat.h" |
3035 | | -#include "pyexpat.h" |
3036 | | - |
3037 | | -/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be |
3038 | | - * cached globally without being in per-module state. |
3039 | | - */ |
3040 | | -static struct PyExpat_CAPI *expat_capi; |
3041 | | -#define EXPAT(func) (expat_capi->func) |
| 3040 | +#define EXPAT(st, func) ((st)->expat_capi->func) |
3042 | 3041 |
|
3043 | 3042 | static XML_Memory_Handling_Suite ExpatMemoryHandler = { |
3044 | 3043 | PyObject_Malloc, PyObject_Realloc, PyObject_Free}; |
@@ -3147,7 +3146,7 @@ expat_set_error(elementtreestate *st, enum XML_Error error_code, |
3147 | 3146 | PyObject *errmsg, *error, *position, *code; |
3148 | 3147 |
|
3149 | 3148 | errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd", |
3150 | | - message ? message : EXPAT(ErrorString)(error_code), |
| 3149 | + message ? message : EXPAT(st, ErrorString)(error_code), |
3151 | 3150 | line, column); |
3152 | 3151 | if (errmsg == NULL) |
3153 | 3152 | return; |
@@ -3227,8 +3226,8 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in, |
3227 | 3226 | expat_set_error( |
3228 | 3227 | st, |
3229 | 3228 | XML_ERROR_UNDEFINED_ENTITY, |
3230 | | - EXPAT(GetErrorLineNumber)(self->parser), |
3231 | | - EXPAT(GetErrorColumnNumber)(self->parser), |
| 3229 | + EXPAT(st, GetErrorLineNumber)(self->parser), |
| 3230 | + EXPAT(st, GetErrorColumnNumber)(self->parser), |
3232 | 3231 | message |
3233 | 3232 | ); |
3234 | 3233 | } |
@@ -3648,24 +3647,23 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, |
3648 | 3647 | Py_CLEAR(self->entity); |
3649 | 3648 | return -1; |
3650 | 3649 | } |
3651 | | - |
3652 | | - self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); |
| 3650 | + elementtreestate *st = self->state; |
| 3651 | + self->parser = EXPAT(st, ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); |
3653 | 3652 | if (!self->parser) { |
3654 | 3653 | Py_CLEAR(self->entity); |
3655 | 3654 | Py_CLEAR(self->names); |
3656 | 3655 | PyErr_NoMemory(); |
3657 | 3656 | return -1; |
3658 | 3657 | } |
3659 | 3658 | /* expat < 2.1.0 has no XML_SetHashSalt() */ |
3660 | | - if (EXPAT(SetHashSalt) != NULL) { |
3661 | | - EXPAT(SetHashSalt)(self->parser, |
| 3659 | + if (EXPAT(st, SetHashSalt) != NULL) { |
| 3660 | + EXPAT(st, SetHashSalt)(self->parser, |
3662 | 3661 | (unsigned long)_Py_HashSecret.expat.hashsalt); |
3663 | 3662 | } |
3664 | 3663 |
|
3665 | 3664 | if (target != Py_None) { |
3666 | 3665 | Py_INCREF(target); |
3667 | 3666 | } else { |
3668 | | - elementtreestate *st = self->state; |
3669 | 3667 | target = treebuilder_new(st->TreeBuilder_Type, NULL, NULL); |
3670 | 3668 | if (!target) { |
3671 | 3669 | Py_CLEAR(self->entity); |
@@ -3713,43 +3711,43 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, |
3713 | 3711 | } |
3714 | 3712 |
|
3715 | 3713 | /* configure parser */ |
3716 | | - EXPAT(SetUserData)(self->parser, self); |
| 3714 | + EXPAT(st, SetUserData)(self->parser, self); |
3717 | 3715 | if (self->handle_start_ns || self->handle_end_ns) |
3718 | | - EXPAT(SetNamespaceDeclHandler)( |
| 3716 | + EXPAT(st, SetNamespaceDeclHandler)( |
3719 | 3717 | self->parser, |
3720 | 3718 | (XML_StartNamespaceDeclHandler) expat_start_ns_handler, |
3721 | 3719 | (XML_EndNamespaceDeclHandler) expat_end_ns_handler |
3722 | 3720 | ); |
3723 | | - EXPAT(SetElementHandler)( |
| 3721 | + EXPAT(st, SetElementHandler)( |
3724 | 3722 | self->parser, |
3725 | 3723 | (XML_StartElementHandler) expat_start_handler, |
3726 | 3724 | (XML_EndElementHandler) expat_end_handler |
3727 | 3725 | ); |
3728 | | - EXPAT(SetDefaultHandlerExpand)( |
| 3726 | + EXPAT(st, SetDefaultHandlerExpand)( |
3729 | 3727 | self->parser, |
3730 | 3728 | (XML_DefaultHandler) expat_default_handler |
3731 | 3729 | ); |
3732 | | - EXPAT(SetCharacterDataHandler)( |
| 3730 | + EXPAT(st, SetCharacterDataHandler)( |
3733 | 3731 | self->parser, |
3734 | 3732 | (XML_CharacterDataHandler) expat_data_handler |
3735 | 3733 | ); |
3736 | 3734 | if (self->handle_comment) |
3737 | | - EXPAT(SetCommentHandler)( |
| 3735 | + EXPAT(st, SetCommentHandler)( |
3738 | 3736 | self->parser, |
3739 | 3737 | (XML_CommentHandler) expat_comment_handler |
3740 | 3738 | ); |
3741 | 3739 | if (self->handle_pi) |
3742 | | - EXPAT(SetProcessingInstructionHandler)( |
| 3740 | + EXPAT(st, SetProcessingInstructionHandler)( |
3743 | 3741 | self->parser, |
3744 | 3742 | (XML_ProcessingInstructionHandler) expat_pi_handler |
3745 | 3743 | ); |
3746 | | - EXPAT(SetStartDoctypeDeclHandler)( |
| 3744 | + EXPAT(st, SetStartDoctypeDeclHandler)( |
3747 | 3745 | self->parser, |
3748 | 3746 | (XML_StartDoctypeDeclHandler) expat_start_doctype_handler |
3749 | 3747 | ); |
3750 | | - EXPAT(SetUnknownEncodingHandler)( |
| 3748 | + EXPAT(st, SetUnknownEncodingHandler)( |
3751 | 3749 | self->parser, |
3752 | | - EXPAT(DefaultUnknownEncodingHandler), NULL |
| 3750 | + EXPAT(st, DefaultUnknownEncodingHandler), NULL |
3753 | 3751 | ); |
3754 | 3752 |
|
3755 | 3753 | return 0; |
@@ -3779,10 +3777,11 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) |
3779 | 3777 | static int |
3780 | 3778 | xmlparser_gc_clear(XMLParserObject *self) |
3781 | 3779 | { |
| 3780 | + elementtreestate *st = self->state; |
3782 | 3781 | if (self->parser != NULL) { |
3783 | 3782 | XML_Parser parser = self->parser; |
3784 | 3783 | self->parser = NULL; |
3785 | | - EXPAT(ParserFree)(parser); |
| 3784 | + EXPAT(st, ParserFree)(parser); |
3786 | 3785 | } |
3787 | 3786 |
|
3788 | 3787 | Py_CLEAR(self->handle_close); |
@@ -3830,17 +3829,17 @@ expat_parse(elementtreestate *st, XMLParserObject *self, const char *data, |
3830 | 3829 | int ok; |
3831 | 3830 |
|
3832 | 3831 | assert(!PyErr_Occurred()); |
3833 | | - ok = EXPAT(Parse)(self->parser, data, data_len, final); |
| 3832 | + ok = EXPAT(st, Parse)(self->parser, data, data_len, final); |
3834 | 3833 |
|
3835 | 3834 | if (PyErr_Occurred()) |
3836 | 3835 | return NULL; |
3837 | 3836 |
|
3838 | 3837 | if (!ok) { |
3839 | 3838 | expat_set_error( |
3840 | 3839 | st, |
3841 | | - EXPAT(GetErrorCode)(self->parser), |
3842 | | - EXPAT(GetErrorLineNumber)(self->parser), |
3843 | | - EXPAT(GetErrorColumnNumber)(self->parser), |
| 3840 | + EXPAT(st, GetErrorCode)(self->parser), |
| 3841 | + EXPAT(st, GetErrorLineNumber)(self->parser), |
| 3842 | + EXPAT(st, GetErrorColumnNumber)(self->parser), |
3844 | 3843 | NULL |
3845 | 3844 | ); |
3846 | 3845 | return NULL; |
@@ -3911,7 +3910,7 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data) |
3911 | 3910 | return NULL; |
3912 | 3911 | } |
3913 | 3912 | /* Explicitly set UTF-8 encoding. Return code ignored. */ |
3914 | | - (void)EXPAT(SetEncoding)(self->parser, "utf-8"); |
| 3913 | + (void)EXPAT(st, SetEncoding)(self->parser, "utf-8"); |
3915 | 3914 |
|
3916 | 3915 | return expat_parse(st, self, data_ptr, (int)data_len, 0); |
3917 | 3916 | } |
@@ -4099,27 +4098,27 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, |
4099 | 4098 | Py_XSETREF(target->end_event_obj, Py_NewRef(event_name_obj)); |
4100 | 4099 | } else if (strcmp(event_name, "start-ns") == 0) { |
4101 | 4100 | Py_XSETREF(target->start_ns_event_obj, Py_NewRef(event_name_obj)); |
4102 | | - EXPAT(SetNamespaceDeclHandler)( |
| 4101 | + EXPAT(st, SetNamespaceDeclHandler)( |
4103 | 4102 | self->parser, |
4104 | 4103 | (XML_StartNamespaceDeclHandler) expat_start_ns_handler, |
4105 | 4104 | (XML_EndNamespaceDeclHandler) expat_end_ns_handler |
4106 | 4105 | ); |
4107 | 4106 | } else if (strcmp(event_name, "end-ns") == 0) { |
4108 | 4107 | Py_XSETREF(target->end_ns_event_obj, Py_NewRef(event_name_obj)); |
4109 | | - EXPAT(SetNamespaceDeclHandler)( |
| 4108 | + EXPAT(st, SetNamespaceDeclHandler)( |
4110 | 4109 | self->parser, |
4111 | 4110 | (XML_StartNamespaceDeclHandler) expat_start_ns_handler, |
4112 | 4111 | (XML_EndNamespaceDeclHandler) expat_end_ns_handler |
4113 | 4112 | ); |
4114 | 4113 | } else if (strcmp(event_name, "comment") == 0) { |
4115 | 4114 | Py_XSETREF(target->comment_event_obj, Py_NewRef(event_name_obj)); |
4116 | | - EXPAT(SetCommentHandler)( |
| 4115 | + EXPAT(st, SetCommentHandler)( |
4117 | 4116 | self->parser, |
4118 | 4117 | (XML_CommentHandler) expat_comment_handler |
4119 | 4118 | ); |
4120 | 4119 | } else if (strcmp(event_name, "pi") == 0) { |
4121 | 4120 | Py_XSETREF(target->pi_event_obj, Py_NewRef(event_name_obj)); |
4122 | | - EXPAT(SetProcessingInstructionHandler)( |
| 4121 | + EXPAT(st, SetProcessingInstructionHandler)( |
4123 | 4122 | self->parser, |
4124 | 4123 | (XML_ProcessingInstructionHandler) expat_pi_handler |
4125 | 4124 | ); |
@@ -4344,14 +4343,14 @@ module_exec(PyObject *m) |
4344 | 4343 | goto error; |
4345 | 4344 |
|
4346 | 4345 | /* link against pyexpat */ |
4347 | | - expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); |
4348 | | - if (expat_capi) { |
| 4346 | + st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); |
| 4347 | + if (st->expat_capi) { |
4349 | 4348 | /* check that it's usable */ |
4350 | | - if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || |
4351 | | - (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) || |
4352 | | - expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || |
4353 | | - expat_capi->MINOR_VERSION != XML_MINOR_VERSION || |
4354 | | - expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { |
| 4349 | + if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || |
| 4350 | + (size_t)st->expat_capi->size < sizeof(struct PyExpat_CAPI) || |
| 4351 | + st->expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || |
| 4352 | + st->expat_capi->MINOR_VERSION != XML_MINOR_VERSION || |
| 4353 | + st->expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { |
4355 | 4354 | PyErr_SetString(PyExc_ImportError, |
4356 | 4355 | "pyexpat version is incompatible"); |
4357 | 4356 | goto error; |
|
0 commit comments