43 lines
1.7 KiB
Python
43 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Keep the type-spec name buffer length C89-safe at its evaluation point."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n"
|
|
r"\{(.*?)\n\}", source, re.S,
|
|
)
|
|
assert match, "PyType_FromModuleAndSpec definition missing"
|
|
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
|
|
opening = body[:body.index(" nmembers = weaklistoffset")]
|
|
assert re.search(r"\bPy_ssize_t name_buf_len;", opening), (
|
|
"name_buf_len must be declared in the opening declaration block (C89), before statements"
|
|
)
|
|
assert len(re.findall(r"\bPy_ssize_t\s+name_buf_len\b", body)) == 1, (
|
|
"declare name_buf_len exactly once"
|
|
)
|
|
assert len(re.findall(r"\bname_buf_len\s*=", body)) == 1, (
|
|
"assign name_buf_len exactly once"
|
|
)
|
|
expected = """
|
|
res->ht_name = PyUnicode_FromString(s);
|
|
if (!res->ht_name) {
|
|
goto fail;
|
|
}
|
|
res->ht_qualname = Py_NewRef(res->ht_name);
|
|
name_buf_len = strlen(spec->name) + 1;
|
|
res->_ht_tpname = PyMem_Malloc(name_buf_len);
|
|
if (res->_ht_tpname == NULL) {
|
|
goto fail;
|
|
}
|
|
type->tp_name = memcpy(res->_ht_tpname, spec->name, name_buf_len);
|
|
res->ht_module = Py_XNewRef(module);
|
|
"""
|
|
actual = body[body.index(" res->ht_name = PyUnicode_FromString(s);"):
|
|
body.index(" if (!bases)")]
|
|
assert actual.split() == expected.split(), (
|
|
"preserve name creation, length evaluation timing, allocation, failure handling, and copy"
|
|
)
|
|
print("PyType_FromModuleAndSpec name_buf_len C89 declaration and same-point initialization: PASS")
|