56 lines
2.3 KiB
Python
56 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Keep the type-spec member loop C89-safe without moving its initialization."""
|
|
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)
|
|
assert re.search(
|
|
r"if \(slot->slot == Py_tp_members\)\s*\{"
|
|
r"\s*const PyMemberDef \*memb;\s*nmembers = 0;"
|
|
r"\s*for \(memb = slot->pfunc; memb->name != NULL; memb\+\+\)\s*\{",
|
|
body,
|
|
), "memb must be declared at block start (C89), with initialization still in the loop header"
|
|
assert len(re.findall(r"\bconst PyMemberDef\s*\*memb\b", body)) == 1, (
|
|
"declare memb exactly once"
|
|
)
|
|
scan = body[body.index(" nmembers = weaklistoffset"):body.index(" res = (PyHeapTypeObject*)")]
|
|
expected = """
|
|
nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0;
|
|
for (slot = spec->slots; slot->slot; slot++) {
|
|
if (slot->slot == Py_tp_members) {
|
|
const PyMemberDef *memb;
|
|
nmembers = 0;
|
|
for (memb = slot->pfunc; memb->name != NULL; memb++) {
|
|
nmembers++;
|
|
if (strcmp(memb->name, "__weaklistoffset__") == 0) {
|
|
assert(memb->type == T_PYSSIZET);
|
|
assert(memb->flags == READONLY);
|
|
weaklistoffset = memb->offset;
|
|
}
|
|
if (strcmp(memb->name, "__dictoffset__") == 0) {
|
|
assert(memb->type == T_PYSSIZET);
|
|
assert(memb->flags == READONLY);
|
|
dictoffset = memb->offset;
|
|
}
|
|
if (strcmp(memb->name, "__vectorcalloffset__") == 0) {
|
|
assert(memb->type == T_PYSSIZET);
|
|
assert(memb->flags == READONLY);
|
|
vectorcalloffset = memb->offset;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
assert scan.split() == expected.split(), (
|
|
"preserve member scan guards, evaluation order, bounds, increments, and offset handling"
|
|
)
|
|
print("PyType_FromModuleAndSpec memb C89 declaration and same-point initialization: PASS")
|