73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Guard VC6-compatible default allocator copies, fields, and call order."""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
source = Path(sys.argv[1]).read_text()
|
|
# Preserve ctx/malloc/calloc/realloc/free and WITH_PYMALLOC selection.
|
|
macros = source[source.index("#define MALLOC_ALLOC"):source.index("typedef struct {", source.index("#define MALLOC_ALLOC"))]
|
|
expected_macros = """
|
|
#define MALLOC_ALLOC {NULL, _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree}
|
|
#ifdef WITH_PYMALLOC
|
|
# define PYMALLOC_ALLOC {NULL, _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free}
|
|
#endif
|
|
#define PYRAW_ALLOC MALLOC_ALLOC
|
|
#ifdef WITH_PYMALLOC
|
|
# define PYOBJ_ALLOC PYMALLOC_ALLOC
|
|
#else
|
|
# define PYOBJ_ALLOC MALLOC_ALLOC
|
|
#endif
|
|
#define PYMEM_ALLOC PYOBJ_ALLOC
|
|
"""
|
|
assert macros.split() == expected_macros.split(), (
|
|
"default allocator fields or WITH_PYMALLOC selection changed"
|
|
)
|
|
|
|
match = re.search(
|
|
r"\npymem_set_default_allocator\([^)]*\)\s*\{(.*?)\n\}", source, re.S
|
|
)
|
|
assert match, "pymem_set_default_allocator definition not found"
|
|
body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S)
|
|
declaration = "PyMemAllocatorEx new_alloc;"
|
|
if body.count(declaration) != 1 or not body.lstrip().startswith(declaration):
|
|
sys.exit("new_alloc must be declared once without initializer at function entry")
|
|
|
|
expected = """
|
|
if (old_alloc != NULL) {
|
|
PyMem_GetAllocator(domain, old_alloc);
|
|
}
|
|
switch(domain)
|
|
{
|
|
case PYMEM_DOMAIN_RAW:
|
|
{
|
|
PyMemAllocatorEx alloc = PYRAW_ALLOC;
|
|
new_alloc = alloc;
|
|
break;
|
|
}
|
|
case PYMEM_DOMAIN_MEM:
|
|
{
|
|
PyMemAllocatorEx alloc = PYMEM_ALLOC;
|
|
new_alloc = alloc;
|
|
break;
|
|
}
|
|
case PYMEM_DOMAIN_OBJ:
|
|
{
|
|
PyMemAllocatorEx alloc = PYOBJ_ALLOC;
|
|
new_alloc = alloc;
|
|
break;
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
PyMem_SetAllocator(domain, &new_alloc);
|
|
if (debug) {
|
|
_PyMem_SetupDebugHooksDomain(domain);
|
|
}
|
|
return 0;
|
|
"""
|
|
if body.replace(declaration, "").split() != expected.split():
|
|
sys.exit("default allocator switch, assignments, or call order changed")
|
|
print("obmalloc default allocator C89 assignments, allocator semantics, and execution order: PASS")
|