#!/usr/bin/env python3 """Check only _PyTuple_DebugMallocStats's C89 index and reporting loop.""" import re import sys from pathlib import Path source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/tupleobject.c") match = re.search( r"void\n_PyTuple_DebugMallocStats\(FILE \*out\)\n\{(.*?)\n\}", source.read_text(), re.S, ) assert match, "_PyTuple_DebugMallocStats definition missing" body = match.group(1) assert re.match( r"\s*#if PyTuple_NFREELISTS > 0\s*" r"PyInterpreterState \*interp = _PyInterpreterState_GET\(\);\s*int i;", body, ), "_PyTuple_DebugMallocStats: i must be declared before the loop for C89" expected = """ #if PyTuple_NFREELISTS > 0 PyInterpreterState *interp = _PyInterpreterState_GET(); int i; for (i = 0; i < PyTuple_NFREELISTS; i++) { int len = i + 1; char buf[128]; PyOS_snprintf(buf, sizeof(buf), "free %d-sized PyTupleObject", len); _PyDebugAllocatorStats(out, buf, STATE.numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, len)); } #endif """ assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), ( "_PyTuple_DebugMallocStats: preserve loop assignment, bounds, increment, " "tuple length, buffer, label, freelist count, and allocation size" ) print("_PyTuple_DebugMallocStats C89 index and reporting loop: PASS")