#!/usr/bin/env python3 """Check debug-only before pointer is C89-declared in bytes formatting.""" import sys from pathlib import Path if len(sys.argv) != 2: raise SystemExit("usage: vc6-bytes-format-c89.test.py bytesobject.c") source = Path(sys.argv[1]).read_text() signature = "_PyBytes_FormatEx(const char *format, Py_ssize_t format_len," start = source.index(signature) body_start = source.index("\n{\n", start) + 2 body_end = source.index("\n}\n", body_start) body = source[body_start:body_end] branch_marker = "else {\n /* Got a format specifier */" branch_start = body.index(branch_marker) branch_end = body.index("\n fmt++;", branch_start) branch = body[branch_start:branch_end] expected_decl = "#ifndef NDEBUG\n char *before;\n#endif" if expected_decl not in branch: raise SystemExit("debug before pointer must be declared in the format-specifier block's declaration group") fmt_statement = body.index("\n fmt++;", branch_start) if branch_start + branch.index(expected_decl) > fmt_statement: raise SystemExit("debug before declaration occurs after executable statements") if source.count("char *before;") != 1 or "char *before = res;" in source: raise SystemExit("debug before pointer must have one declaration and a separate assignment") prepare = body.index("_PyBytesWriter_Prepare(&writer, res, alloc - 2)") assignment = body.index("before = res;") assertion = body.index("assert((res - before) == alloc);") if not (prepare < assignment < body.index("/* Write the sign if needed */") < assertion): raise SystemExit("bytes format pointer capture / output / size assertion order changed") print("bytes format debug pointer C89 declaration and capture order: PASS")