|
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