port: expand VC6 C89 core frontier
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Focused Visual C++ 6.0 C89 regression checks for memoryobject.c."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1]).read_text()
|
||||
|
||||
match = re.search(
|
||||
r"static int\s+copy_single\(PyMemoryViewObject \*self, const Py_buffer \*dest, const Py_buffer \*src\)\s*\{(?P<body>.*?)\n\}",
|
||||
source,
|
||||
re.S,
|
||||
)
|
||||
assert match, "copy_single definition not found"
|
||||
body = match.group("body")
|
||||
expected = """
|
||||
char *mem;
|
||||
CHECK_RELEASED_INT_AGAIN(self);
|
||||
mem = NULL;
|
||||
"""
|
||||
assert body.split()[:len(expected.split())] == expected.split(), (
|
||||
"copy_single must declare mem before the release-check macro while keeping its initialization after the check"
|
||||
)
|
||||
assert "char *mem =" not in body, "copy_single must not initialize mem before the release check"
|
||||
print("memoryobject copy_single C89 local and release-check order: PASS")
|
||||
|
||||
assert not re.search(r"\blong\s+long\b", source), "memoryobject must use PY_LONG_LONG spellings supported by VC6"
|
||||
assert re.search(r"\bPY_LONG_LONG\b", source), "memoryobject must retain native 64-bit format support through PY_LONG_LONG"
|
||||
assert not re.search(r"\b_Bool\b", source), "memoryobject must use the VC6-compatible one-byte bool representation"
|
||||
assert "case '?': UNPACK_SINGLE(ld, ptr, unsigned char); goto convert_bool;" in source, "memoryobject bool unpacking must preserve nonzero-to-bool conversion"
|
||||
assert "PACK_SINGLE(ptr, ld, unsigned char);" in source, "memoryobject bool packing must use a one-byte type after PyObject_IsTrue normalization"
|
||||
print("memoryobject VC6 64-bit and bool format spellings: PASS")
|
||||
|
||||
match = re.search(r"static PyObject \*\s*memoryiter_next\(memoryiterobject \*it\)\s*\{(?P<body>.*?)\n\}", source, re.S)
|
||||
assert match, "memoryiter_next definition not found"
|
||||
body = match.group("body")
|
||||
assert "Py_buffer *view =" not in body and "char *ptr =" not in body, "memoryiter_next must not declare locals after CHECK_RELEASED"
|
||||
assert "if (it->it_index < it->it_length) {\n Py_buffer *view;\n char *ptr;\n\n CHECK_RELEASED(seq);\n view = &(seq->view);\n ptr = (char *)seq->view.buf;" in body, "memoryiter_next must declare conditional locals before release checks and preserve pointer setup order"
|
||||
print("memoryobject memoryiter_next C89 locals and release-check order: PASS")
|
||||
|
||||
match = re.search(r"static PyObject \*\s*memory_iter\(PyObject \*seq\)\s*\{(?P<body>.*?)\n\}", source, re.S)
|
||||
assert match, "memory_iter definition not found"
|
||||
body = match.group("body")
|
||||
expected = """
|
||||
PyMemoryViewObject *obj;
|
||||
int ndims;
|
||||
const char *fmt;
|
||||
memoryiterobject *it;
|
||||
if (!PyMemoryView_Check(seq))
|
||||
"""
|
||||
assert body.split()[:len(expected.split())] == expected.split(), "memory_iter must declare locals before validation"
|
||||
ordered = ("if (!PyMemoryView_Check(seq))", "obj = (PyMemoryViewObject *)seq;", "ndims = obj->view.ndim;", "fmt = adjust_fmt(&obj->view);", "it = PyObject_GC_New(memoryiterobject, &_PyMemoryIter_Type);")
|
||||
positions = [body.find(token) for token in ordered]
|
||||
assert all(position >= 0 for position in positions) and positions == sorted(positions), "memory_iter must preserve validation, type/shape setup, format adjustment, and allocation order"
|
||||
assert not re.search(r"\b(?:PyMemoryViewObject|int|const char|memoryiterobject)\s+\*?\w+\s*=", body), "memory_iter must not retain late initialized declarations"
|
||||
print("memoryobject memory_iter C89 locals and iterator allocation order: PASS")
|
||||
|
||||
match = re.search(r"PyTypeObject _PyMemoryIter_Type = \{(?P<body>.*?)\n\};", source, re.S)
|
||||
assert match, "_PyMemoryIter_Type initializer not found"
|
||||
body = match.group("body")
|
||||
assert ".tp_" not in body, "_PyMemoryIter_Type must use positional fields instead of C99 designated initializers"
|
||||
expected = (
|
||||
"PyVarObject_HEAD_INIT(&PyType_Type, 0)",
|
||||
'"memory_iterator"',
|
||||
"sizeof(memoryiterobject)",
|
||||
"0,",
|
||||
"(destructor)memoryiter_dealloc",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"PyObject_GenericGetAttr",
|
||||
"0,",
|
||||
"0,",
|
||||
"Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC",
|
||||
"0,",
|
||||
"(traverseproc)memoryiter_traverse",
|
||||
"0,",
|
||||
"0,",
|
||||
"0,",
|
||||
"PyObject_SelfIter",
|
||||
"(iternextfunc)memoryiter_next",
|
||||
)
|
||||
positions = []
|
||||
cursor = 0
|
||||
for token in expected:
|
||||
position = body.find(token, cursor)
|
||||
positions.append(position)
|
||||
if position >= 0:
|
||||
cursor = position + len(token)
|
||||
assert all(position >= 0 for position in positions), "_PyMemoryIter_Type positional initializer must preserve all configured field slots"
|
||||
print("memoryobject _PyMemoryIter_Type C89 positional initializer: PASS")
|
||||
Reference in New Issue
Block a user