| @@ -51,6 +51,26 @@ call_tag_def_func(const char* funcname, PyObject* tag) | |||||
| return ans; | return ans; | ||||
| } | } | ||||
| /* | |||||
| Sanitize the name of a tag so it can be compared with others for equality. | |||||
| */ | |||||
| static PyObject* | |||||
| strip_tag_name(PyObject* token) | |||||
| { | |||||
| PyObject *text, *rstripped, *lowered; | |||||
| text = PyObject_GetAttrString(token, "text"); | |||||
| if (!text) | |||||
| return NULL; | |||||
| rstripped = PyObject_CallMethod(text, "rstrip", NULL); | |||||
| Py_DECREF(text); | |||||
| if (!rstripped) | |||||
| return NULL; | |||||
| lowered = PyObject_CallMethod(rstripped, "rstrip", NULL); | |||||
| Py_DECREF(rstripped); | |||||
| return lowered; | |||||
| } | |||||
| static Textbuffer* | static Textbuffer* | ||||
| Textbuffer_new(void) | Textbuffer_new(void) | ||||
| { | { | ||||
| @@ -1629,7 +1649,56 @@ Tokenizer_handle_tag_open_close(Tokenizer* self) | |||||
| static PyObject* | static PyObject* | ||||
| Tokenizer_handle_tag_close_close(Tokenizer* self) | Tokenizer_handle_tag_close_close(Tokenizer* self) | ||||
| { | { | ||||
| return NULL; | |||||
| PyObject *closing, *first, *so, *sc, *token; | |||||
| int valid = 1; | |||||
| closing = Tokenizer_pop(self); | |||||
| if (!closing) | |||||
| return NULL; | |||||
| if (PyList_GET_SIZE(closing) != 1) | |||||
| valid = 0; | |||||
| else { | |||||
| first = PyList_GET_ITEM(closing, 0); | |||||
| switch (PyObject_IsInstance(first, Text)) { | |||||
| case 0: | |||||
| valid = 0; | |||||
| break; | |||||
| case 1: { | |||||
| so = strip_tag_name(first); | |||||
| sc = strip_tag_name(PyList_GET_ITEM(self->topstack->stack, 1)); | |||||
| if (so && sc) { | |||||
| if (PyUnicode_Compare(so, sc)) | |||||
| valid = 0; | |||||
| Py_DECREF(so); | |||||
| Py_DECREF(sc); | |||||
| break; | |||||
| } | |||||
| Py_XDECREF(so); | |||||
| Py_XDECREF(sc); | |||||
| } | |||||
| case -1: | |||||
| Py_DECREF(closing); | |||||
| return NULL; | |||||
| } | |||||
| } | |||||
| if (!valid) { | |||||
| Py_DECREF(closing); | |||||
| return Tokenizer_fail_route(self); | |||||
| } | |||||
| if (Tokenizer_emit_all(self, closing)) { | |||||
| Py_DECREF(closing); | |||||
| return NULL; | |||||
| } | |||||
| Py_DECREF(closing); | |||||
| token = PyObject_CallObject(TagCloseClose, NULL); | |||||
| if (!token) | |||||
| return NULL; | |||||
| if (Tokenizer_emit(self, token)) { | |||||
| Py_DECREF(token); | |||||
| return NULL; | |||||
| } | |||||
| Py_DECREF(token); | |||||
| return Tokenizer_pop(self); | |||||
| } | } | ||||
| /* | /* | ||||