Files
Python3-Win9x/scripts/vc6-odict-number-c89.test.py
T

48 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Compile the exact odict number table as C89 and check every named slot."""
import re
import subprocess
import sys
import tempfile
from pathlib import Path
source_path = Path(sys.argv[1])
source = source_path.read_text()
match = re.search(r"static PyNumberMethods odict_as_number = \{.*?\n\};", source, re.S)
assert match, "odict_as_number initializer not found"
header = (source_path.parent.parent / "Include/cpython/object.h").read_text()
layout = re.search(r"typedef struct \{([^{}]*)\} PyNumberMethods;", header, re.S)
assert layout, "PyNumberMethods layout not found"
# Use the actual header's order and types; check slots by name, not position.
body = re.sub(r"/\*.*?\*/", "", layout.group(1), flags=re.S)
fields = re.findall(r"\b(nb_\w+)\s*;", body)
assert len(fields) == 36 and len(set(fields)) == 36
harness = r'''
#include <assert.h>
typedef struct { int value; } PyObject;
typedef PyObject *(*binaryfunc)(PyObject *, PyObject *);
typedef PyObject *(*ternaryfunc)(PyObject *, PyObject *, PyObject *);
typedef PyObject *(*unaryfunc)(PyObject *);
typedef int (*inquiry)(PyObject *);
static PyObject *odict_or(PyObject *a, PyObject *b) { (void)b; return a; }
static PyObject *odict_inplace_or(PyObject *a, PyObject *b) { (void)a; return b; }
'''
harness += "typedef struct {" + body + "} PyNumberMethods;\n"
harness += match.group(0) + "\nint main(void) {\n"
for field in fields:
expected = {"nb_or": "odict_or", "nb_inplace_or": "odict_inplace_or"}.get(field, "0")
harness += f" assert(odict_as_number.{field} == {expected});\n"
harness += " return 0;\n}\n"
with tempfile.TemporaryDirectory(prefix="vc6-odict-number-") as directory:
path = Path(directory)
(path / "test.c").write_text(harness)
result = subprocess.run([
"cc", "-std=c89", "-pedantic-errors", "-Wall", "-Wextra", "-Werror",
str(path / "test.c"), "-o", str(path / "test"),
])
if result.returncode:
sys.exit(result.returncode)
subprocess.run([str(path / "test")], check=True)
print("odict_as_number C89 compile and all 36 semantic field mappings: PASS")